blob: 0d4be1d8112a46e8b330e5cc56be1600f2102d40 [file] [log] [blame]
Alexandre Ramesd3832962016-07-04 15:03:43 +01001// 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
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010027#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
Alexandre Ramesd3832962016-07-04 15:03:43 +010028
Jacob Bramley85a9c102019-12-09 17:48:29 +000029#include <errno.h>
30#include <unistd.h>
31
Alexandre Ramesd3832962016-07-04 15:03:43 +010032#include <cmath>
Pierre Langlois1bce0072017-06-06 17:58:58 +010033#include <cstring>
Martyn Capewell5b24fb32016-11-02 18:52:55 +000034#include <limits>
Alexandre Ramesd3832962016-07-04 15:03:43 +010035
Alexandre Ramesb49bdb72016-09-26 12:08:57 +010036#include "simulator-aarch64.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010037
38namespace vixl {
39namespace aarch64 {
40
Jacob Bramleyca789742018-09-13 14:25:46 +010041using vixl::internal::SimFloat16;
42
Alexandre Ramesd3832962016-07-04 15:03:43 +010043const Instruction* Simulator::kEndOfSimAddress = NULL;
44
45void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
46 int width = msb - lsb + 1;
47 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
48
49 bits <<= lsb;
50 uint32_t mask = ((1 << width) - 1) << lsb;
51 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
52
53 value_ = (value_ & ~mask) | (bits & mask);
54}
55
56
57SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
58 switch (id) {
59 case NZCV:
60 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
61 case FPCR:
62 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
63 default:
64 VIXL_UNREACHABLE();
65 return SimSystemRegister();
66 }
67}
68
69
Martyn Capewellec07c892020-08-03 15:15:58 +010070Simulator::FormToVisitorFnMap Simulator::form_to_visitor_ = {
Martyn Capewell6bf28752020-08-05 11:57:06 +010071 DEFAULT_FORM_TO_VISITOR_MAP(Simulator),
72 {"adclb_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
73 {"adclt_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
74 {"addhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
75 {"addhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
76 {"addp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
77 {"bcax_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
78 {"bdep_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
79 {"bext_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
80 {"bgrp_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
81 {"bsl1n_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
82 {"bsl2n_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
83 {"bsl_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
84 {"cadd_z_zz", &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
85 {"cdot_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb_const},
86 {"cdot_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnH_ZmH_imm_const},
87 {"cdot_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnB_ZmB_imm_const},
88 {"cmla_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT_const},
89 {"cmla_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm_const},
90 {"cmla_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm_const},
91 {"eor3_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
92 {"eorbt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
93 {"eortb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
94 {"ext_z_zi_con", &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm},
95 {"faddp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
96 {"fcvtlt_z_p_z_h2s", &Simulator::Simulate_ZdS_PgM_ZnH},
97 {"fcvtlt_z_p_z_s2d", &Simulator::Simulate_ZdD_PgM_ZnS},
98 {"fcvtnt_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
99 {"fcvtnt_z_p_z_s2h", &Simulator::Simulate_ZdH_PgM_ZnS},
100 {"fcvtx_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
101 {"fcvtxnt_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
102 {"flogb_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
103 {"fmaxnmp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
104 {"fmaxp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
105 {"fminnmp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
106 {"fminp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
107 {"fmlalb_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
108 {"fmlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
109 {"fmlalt_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
110 {"fmlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
111 {"fmlslb_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
112 {"fmlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
113 {"fmlslt_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
114 {"fmlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
115 {"histcnt_z_p_zz", &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT},
116 {"histseg_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
117 {"ldnt1b_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
118 {"ldnt1b_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
119 {"ldnt1d_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
120 {"ldnt1h_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
121 {"ldnt1h_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
122 {"ldnt1sb_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
123 {"ldnt1sb_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
124 {"ldnt1sh_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
125 {"ldnt1sh_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
126 {"ldnt1sw_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
127 {"ldnt1w_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
128 {"ldnt1w_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
129 {"match_p_p_zz", &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
130 {"mla_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
131 {"mla_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
132 {"mla_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
133 {"mls_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
134 {"mls_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
135 {"mls_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
136 {"mul_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
137 {"mul_z_zzi_d", &Simulator::Simulate_ZdD_ZnD_ZmD_imm},
138 {"mul_z_zzi_h", &Simulator::Simulate_ZdH_ZnH_ZmH_imm},
139 {"mul_z_zzi_s", &Simulator::Simulate_ZdS_ZnS_ZmS_imm},
140 {"nbsl_z_zzz", &Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD},
141 {"nmatch_p_p_zz", &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
142 {"pmul_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
143 {"pmullb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
144 {"pmullt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
145 {"raddhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
146 {"raddhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
147 {"rshrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
148 {"rshrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
149 {"rsubhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
150 {"rsubhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
151 {"saba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
152 {"sabalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
153 {"sabalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
154 {"sabdlb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
155 {"sabdlt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
156 {"sadalp_z_p_z", &Simulator::Simulate_ZdaT_PgM_ZnTb},
157 {"saddlb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
158 {"saddlbt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
159 {"saddlt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
160 {"saddwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
161 {"saddwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
162 {"sbclb_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
163 {"sbclt_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
164 {"shadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
165 {"shrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
166 {"shrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
167 {"shsub_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
168 {"shsubr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
169 {"sli_z_zzi", &Simulator::Simulate_ZdT_ZnT_const},
170 {"smaxp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
171 {"sminp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
172 {"smlalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
173 {"smlalb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
174 {"smlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
175 {"smlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
176 {"smlalt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
177 {"smlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
178 {"smlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
179 {"smlslb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
180 {"smlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
181 {"smlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
182 {"smlslt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
183 {"smlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
184 {"smulh_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
185 {"smullb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
186 {"smullb_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
187 {"smullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
188 {"smullt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
189 {"smullt_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
190 {"smullt_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
191 {"splice_z_p_zz_con", &Simulator::Simulate_ZdT_Pg_Zn1T_Zn2T},
192 {"sqabs_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
193 {"sqadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
194 {"sqcadd_z_zz", &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
195 {"sqdmlalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
196 {"sqdmlalb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
197 {"sqdmlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
198 {"sqdmlalbt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
199 {"sqdmlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
200 {"sqdmlalt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
201 {"sqdmlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
202 {"sqdmlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
203 {"sqdmlslb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
204 {"sqdmlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
205 {"sqdmlslbt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
206 {"sqdmlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
207 {"sqdmlslt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
208 {"sqdmlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
209 {"sqdmulh_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
210 {"sqdmulh_z_zzi_d", &Simulator::Simulate_ZdD_ZnD_ZmD_imm},
211 {"sqdmulh_z_zzi_h", &Simulator::Simulate_ZdH_ZnH_ZmH_imm},
212 {"sqdmulh_z_zzi_s", &Simulator::Simulate_ZdS_ZnS_ZmS_imm},
213 {"sqdmullb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
214 {"sqdmullb_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
215 {"sqdmullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
216 {"sqdmullt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
217 {"sqdmullt_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
218 {"sqdmullt_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
219 {"sqneg_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
220 {"sqrdcmlah_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT_const},
221 {"sqrdcmlah_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm_const},
222 {"sqrdcmlah_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm_const},
223 {"sqrdmlah_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
224 {"sqrdmlah_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
225 {"sqrdmlah_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
226 {"sqrdmlah_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
227 {"sqrdmlsh_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
228 {"sqrdmlsh_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
229 {"sqrdmlsh_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
230 {"sqrdmlsh_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
231 {"sqrdmulh_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
232 {"sqrdmulh_z_zzi_d", &Simulator::Simulate_ZdD_ZnD_ZmD_imm},
233 {"sqrdmulh_z_zzi_h", &Simulator::Simulate_ZdH_ZnH_ZmH_imm},
234 {"sqrdmulh_z_zzi_s", &Simulator::Simulate_ZdS_ZnS_ZmS_imm},
235 {"sqrshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
236 {"sqrshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
237 {"sqrshrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
238 {"sqrshrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
239 {"sqrshrunb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
240 {"sqrshrunt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
241 {"sqshl_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
242 {"sqshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
243 {"sqshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
244 {"sqshlu_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
245 {"sqshrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
246 {"sqshrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
247 {"sqshrunb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
248 {"sqshrunt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
249 {"sqsub_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
250 {"sqsubr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
251 {"sqxtnb_z_zz", &Simulator::Simulate_ZdT_ZnTb},
252 {"sqxtnt_z_zz", &Simulator::Simulate_ZdT_ZnTb},
253 {"sqxtunb_z_zz", &Simulator::Simulate_ZdT_ZnTb},
254 {"sqxtunt_z_zz", &Simulator::Simulate_ZdT_ZnTb},
255 {"srhadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
256 {"sri_z_zzi", &Simulator::Simulate_ZdT_ZnT_const},
257 {"srshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
258 {"srshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
259 {"srshr_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
260 {"srsra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
261 {"sshllb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
262 {"sshllt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
263 {"ssra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
264 {"ssublb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
265 {"ssublbt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
266 {"ssublt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
267 {"ssubltb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
268 {"ssubwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
269 {"ssubwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
270 {"stnt1b_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
271 {"stnt1b_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
272 {"stnt1d_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
273 {"stnt1h_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
274 {"stnt1h_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
275 {"stnt1w_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
276 {"stnt1w_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
277 {"subhnb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
278 {"subhnt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
279 {"suqadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
280 {"tbl_z_zz_2", &Simulator::Simulate_ZdT_Zn1T_Zn2T_ZmT},
281 {"tbx_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
282 {"uaba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
283 {"uabalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
284 {"uabalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
285 {"uabdlb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
286 {"uabdlt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
287 {"uadalp_z_p_z", &Simulator::Simulate_ZdaT_PgM_ZnTb},
288 {"uaddlb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
289 {"uaddlt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
290 {"uaddwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
291 {"uaddwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
292 {"uhadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
293 {"uhsub_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
294 {"uhsubr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
295 {"umaxp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
296 {"uminp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
297 {"umlalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
298 {"umlalb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
299 {"umlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
300 {"umlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
301 {"umlalt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
302 {"umlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
303 {"umlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
304 {"umlslb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
305 {"umlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
306 {"umlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
307 {"umlslt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
308 {"umlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
309 {"umulh_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
310 {"umullb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
311 {"umullb_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
312 {"umullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
313 {"umullt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
314 {"umullt_z_zzi_d", &Simulator::Simulate_ZdD_ZnS_ZmS_imm},
315 {"umullt_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
316 {"uqadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
317 {"uqrshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
318 {"uqrshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
319 {"uqrshrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
320 {"uqrshrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
321 {"uqshl_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
322 {"uqshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
323 {"uqshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
324 {"uqshrnb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
325 {"uqshrnt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
326 {"uqsub_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
327 {"uqsubr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
328 {"uqxtnb_z_zz", &Simulator::Simulate_ZdT_ZnTb},
329 {"uqxtnt_z_zz", &Simulator::Simulate_ZdT_ZnTb},
330 {"urecpe_z_p_z", &Simulator::Simulate_ZdS_PgM_ZnS},
331 {"urhadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
332 {"urshl_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
333 {"urshlr_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
334 {"urshr_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
335 {"ursqrte_z_p_z", &Simulator::Simulate_ZdS_PgM_ZnS},
336 {"ursra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
337 {"ushllb_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
338 {"ushllt_z_zi", &Simulator::Simulate_ZdT_ZnTb_const},
339 {"usqadd_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
340 {"usra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
341 {"usublb_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
342 {"usublt_z_zz", &Simulator::Simulate_ZdT_ZnTb_ZmTb},
343 {"usubwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
344 {"usubwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
345 {"whilege_p_p_rr", &Simulator::Simulate_PdT_Rn_Rm},
346 {"whilegt_p_p_rr", &Simulator::Simulate_PdT_Rn_Rm},
347 {"whilehi_p_p_rr", &Simulator::Simulate_PdT_Rn_Rm},
348 {"whilehs_p_p_rr", &Simulator::Simulate_PdT_Rn_Rm},
349 {"whilerw_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
350 {"whilewr_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
351 {"xar_z_zzi", &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
352};
Martyn Capewell8c691852020-07-15 18:33:15 +0100353
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100354Simulator::Simulator(Decoder* decoder, FILE* stream)
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +0100355 : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100356 // Ensure that shift operations act as the simulator expects.
357 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
358 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
359
Jacob Bramley85a9c102019-12-09 17:48:29 +0000360 // Set up a dummy pipe for CanReadMemory.
361 VIXL_CHECK(pipe(dummy_pipe_fd_) == 0);
362
Alexandre Ramesd3832962016-07-04 15:03:43 +0100363 // Set up the decoder.
364 decoder_ = decoder;
365 decoder_->AppendVisitor(this);
366
367 stream_ = stream;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100368
Alexandre Ramesd3832962016-07-04 15:03:43 +0100369 print_disasm_ = new PrintDisassembler(stream_);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100370 // The Simulator and Disassembler share the same available list, held by the
371 // auditor. The Disassembler only annotates instructions with features that
372 // are _not_ available, so registering the auditor should have no effect
373 // unless the simulator is about to abort (due to missing features). In
374 // practice, this means that with trace enabled, the simulator will crash just
375 // after the disassembler prints the instruction, with the missing features
376 // enumerated.
377 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
378
Alexandre Ramesd3832962016-07-04 15:03:43 +0100379 SetColouredTrace(false);
380 trace_parameters_ = LOG_NONE;
381
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100382 // We have to configure the SVE vector register length before calling
383 // ResetState().
384 SetVectorLengthInBits(kZRegMinSize);
385
Alexandre Ramesd3832962016-07-04 15:03:43 +0100386 ResetState();
387
388 // Allocate and set up the simulator stack.
389 stack_ = new byte[stack_size_];
390 stack_limit_ = stack_ + stack_protection_size_;
391 // Configure the starting stack pointer.
392 // - Find the top of the stack.
393 byte* tos = stack_ + stack_size_;
394 // - There's a protection region at both ends of the stack.
395 tos -= stack_protection_size_;
396 // - The stack pointer must be 16-byte aligned.
397 tos = AlignDown(tos, 16);
398 WriteSp(tos);
399
Alexandre Ramesd3832962016-07-04 15:03:43 +0100400 // Print a warning about exclusive-access instructions, but only the first
401 // time they are encountered. This warning can be silenced using
402 // SilenceExclusiveAccessWarning().
403 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100404
405 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800406
407 // Initialize the common state of RNDR and RNDRRS.
408 uint16_t seed[3] = {11, 22, 33};
Jacob Bramley85a9c102019-12-09 17:48:29 +0000409 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
410 memcpy(rand_state_, seed, sizeof(rand_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700411
412 // Initialize all bits of pseudo predicate register to true.
413 LogicPRegister ones(pregister_all_true_);
414 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100415}
416
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100417void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100418 // Reset the system registers.
419 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
420 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
TatWai Chong4023d7a2019-11-18 14:16:28 -0800421 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100422}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100423
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100424void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100425 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
426 WriteXRegister(i, 0xbadbeef);
427 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100428 // Returning to address 0 exits the Simulator.
429 WriteLr(kEndOfSimAddress);
430}
Pierre Langlois23703a72016-08-15 17:23:39 +0100431
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100432void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800433 // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100434 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
435 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800436 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100437 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100438 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100439 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800440 // Encode the register number and (D-sized) lane into each NaN, to
441 // make them easier to trace.
442 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
443 (0x0000000000000001 * lane);
444 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
445 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100446 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800447 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100448 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100449}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800450
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100451void Simulator::ResetPRegisters() {
452 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
453 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
454 // Ensure the register configuration fits in this bit encoding.
455 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
456 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700457 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100458 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
459 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700460 // Encode the register number and (H-sized) lane into each lane slot.
461 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100462 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700463 }
464 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100465}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700466
TatWai Chong4023d7a2019-11-18 14:16:28 -0800467void Simulator::ResetFFR() {
468 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
469 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
470 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
471}
472
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100473void Simulator::ResetState() {
474 ResetSystemRegisters();
475 ResetRegisters();
476 ResetVRegisters();
477 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100478
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100479 pc_ = NULL;
480 pc_modified_ = false;
481
482 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100483 btype_ = DefaultBType;
484 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100485}
486
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100487void Simulator::SetVectorLengthInBits(unsigned vector_length) {
488 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
489 (vector_length <= kZRegMaxSize));
490 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
491 vector_length_ = vector_length;
492
493 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
494 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
495 }
496 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
497 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
498 }
499
TatWai Chong4023d7a2019-11-18 14:16:28 -0800500 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
501
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100502 ResetVRegisters();
503 ResetPRegisters();
TatWai Chong4023d7a2019-11-18 14:16:28 -0800504 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100505}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100506
507Simulator::~Simulator() {
508 delete[] stack_;
509 // The decoder may outlive the simulator.
510 decoder_->RemoveVisitor(print_disasm_);
511 delete print_disasm_;
Jacob Bramley85a9c102019-12-09 17:48:29 +0000512 close(dummy_pipe_fd_[0]);
513 close(dummy_pipe_fd_[1]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100514}
515
516
517void Simulator::Run() {
518 // Flush any written registers before executing anything, so that
519 // manually-set registers are logged _before_ the first instruction.
520 LogAllWrittenRegisters();
521
522 while (pc_ != kEndOfSimAddress) {
523 ExecuteInstruction();
524 }
525}
526
527
528void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100529 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100530 Run();
531}
532
533
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100534// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100535const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
536 "x6", "x7", "x8", "x9", "x10", "x11",
537 "x12", "x13", "x14", "x15", "x16", "x17",
538 "x18", "x19", "x20", "x21", "x22", "x23",
539 "x24", "x25", "x26", "x27", "x28", "x29",
540 "lr", "xzr", "sp"};
541
542const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
543 "w6", "w7", "w8", "w9", "w10", "w11",
544 "w12", "w13", "w14", "w15", "w16", "w17",
545 "w18", "w19", "w20", "w21", "w22", "w23",
546 "w24", "w25", "w26", "w27", "w28", "w29",
547 "w30", "wzr", "wsp"};
548
Jacob Bramley423e5422019-11-13 19:15:55 +0000549const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
550 "b6", "b7", "b8", "b9", "b10", "b11",
551 "b12", "b13", "b14", "b15", "b16", "b17",
552 "b18", "b19", "b20", "b21", "b22", "b23",
553 "b24", "b25", "b26", "b27", "b28", "b29",
554 "b30", "b31"};
555
Carey Williamsd8bb3572018-04-10 11:58:07 +0100556const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
557 "h6", "h7", "h8", "h9", "h10", "h11",
558 "h12", "h13", "h14", "h15", "h16", "h17",
559 "h18", "h19", "h20", "h21", "h22", "h23",
560 "h24", "h25", "h26", "h27", "h28", "h29",
561 "h30", "h31"};
562
Alexandre Ramesd3832962016-07-04 15:03:43 +0100563const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
564 "s6", "s7", "s8", "s9", "s10", "s11",
565 "s12", "s13", "s14", "s15", "s16", "s17",
566 "s18", "s19", "s20", "s21", "s22", "s23",
567 "s24", "s25", "s26", "s27", "s28", "s29",
568 "s30", "s31"};
569
570const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
571 "d6", "d7", "d8", "d9", "d10", "d11",
572 "d12", "d13", "d14", "d15", "d16", "d17",
573 "d18", "d19", "d20", "d21", "d22", "d23",
574 "d24", "d25", "d26", "d27", "d28", "d29",
575 "d30", "d31"};
576
577const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
578 "v6", "v7", "v8", "v9", "v10", "v11",
579 "v12", "v13", "v14", "v15", "v16", "v17",
580 "v18", "v19", "v20", "v21", "v22", "v23",
581 "v24", "v25", "v26", "v27", "v28", "v29",
582 "v30", "v31"};
583
TatWai Chong72d2e562019-05-16 11:22:22 -0700584const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
585 "z6", "z7", "z8", "z9", "z10", "z11",
586 "z12", "z13", "z14", "z15", "z16", "z17",
587 "z18", "z19", "z20", "z21", "z22", "z23",
588 "z24", "z25", "z26", "z27", "z28", "z29",
589 "z30", "z31"};
590
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100591const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
592 "p6", "p7", "p8", "p9", "p10", "p11",
593 "p12", "p13", "p14", "p15"};
594// clang-format on
595
Alexandre Ramesd3832962016-07-04 15:03:43 +0100596
597const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100598 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000599 if ((code == kSPRegInternalCode) ||
600 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100601 code = kZeroRegCode + 1;
602 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000603 VIXL_ASSERT(code < ArrayLength(wreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100604 return wreg_names[code];
605}
606
607
608const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100609 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000610 if ((code == kSPRegInternalCode) ||
611 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100612 code = kZeroRegCode + 1;
613 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000614 VIXL_ASSERT(code < ArrayLength(xreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100615 return xreg_names[code];
616}
617
618
Jacob Bramley423e5422019-11-13 19:15:55 +0000619const char* Simulator::BRegNameForCode(unsigned code) {
620 VIXL_ASSERT(code < kNumberOfVRegisters);
621 return breg_names[code];
622}
623
624
Carey Williamsd8bb3572018-04-10 11:58:07 +0100625const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100626 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100627 return hreg_names[code];
628}
629
630
Alexandre Ramesd3832962016-07-04 15:03:43 +0100631const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100632 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100633 return sreg_names[code];
634}
635
636
637const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100638 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100639 return dreg_names[code];
640}
641
642
643const char* Simulator::VRegNameForCode(unsigned code) {
644 VIXL_ASSERT(code < kNumberOfVRegisters);
645 return vreg_names[code];
646}
647
648
TatWai Chong72d2e562019-05-16 11:22:22 -0700649const char* Simulator::ZRegNameForCode(unsigned code) {
650 VIXL_ASSERT(code < kNumberOfZRegisters);
651 return zreg_names[code];
652}
653
654
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100655const char* Simulator::PRegNameForCode(unsigned code) {
656 VIXL_ASSERT(code < kNumberOfPRegisters);
657 return preg_names[code];
658}
659
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000660SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
661 SimVRegister ones, result;
662 dup_immediate(kFormatVnB, ones, 0xff);
663 mov_zeroing(kFormatVnB, result, pg, ones);
664 return result;
665}
666
TatWai Chong47c26842020-02-10 01:51:32 -0800667void Simulator::ExtractFromSimVRegister(VectorFormat vform,
668 SimPRegister& pd,
669 SimVRegister vreg) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000670 SimVRegister zero;
671 dup_immediate(kFormatVnB, zero, 0);
672 SVEIntCompareVectorsHelper(ne,
TatWai Chong47c26842020-02-10 01:51:32 -0800673 vform,
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000674 pd,
675 GetPTrue(),
676 vreg,
677 zero,
678 false,
679 LeaveFlags);
680}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100681
Alexandre Ramesd3832962016-07-04 15:03:43 +0100682#define COLOUR(colour_code) "\033[0;" colour_code "m"
683#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100684#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100685#define NORMAL ""
686#define GREY "30"
687#define RED "31"
688#define GREEN "32"
689#define YELLOW "33"
690#define BLUE "34"
691#define MAGENTA "35"
692#define CYAN "36"
693#define WHITE "37"
694void Simulator::SetColouredTrace(bool value) {
695 coloured_trace_ = value;
696
697 clr_normal = value ? COLOUR(NORMAL) : "";
698 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
699 clr_flag_value = value ? COLOUR(NORMAL) : "";
700 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
701 clr_reg_value = value ? COLOUR(CYAN) : "";
702 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
703 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100704 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
705 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100706 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
707 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
708 clr_warning_message = value ? COLOUR(YELLOW) : "";
709 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100710 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100711
712 if (value) {
713 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
714 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
715 } else {
716 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
717 print_disasm_->SetCPUFeaturesSuffix("");
718 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100719}
720
721
722void Simulator::SetTraceParameters(int parameters) {
723 bool disasm_before = trace_parameters_ & LOG_DISASM;
724 trace_parameters_ = parameters;
725 bool disasm_after = trace_parameters_ & LOG_DISASM;
726
727 if (disasm_before != disasm_after) {
728 if (disasm_after) {
729 decoder_->InsertVisitorBefore(print_disasm_, this);
730 } else {
731 decoder_->RemoveVisitor(print_disasm_);
732 }
733 }
734}
735
736
Alexandre Ramesd3832962016-07-04 15:03:43 +0100737// Helpers ---------------------------------------------------------------------
738uint64_t Simulator::AddWithCarry(unsigned reg_size,
739 bool set_flags,
740 uint64_t left,
741 uint64_t right,
742 int carry_in) {
743 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
744 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
745
746 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
747 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
748 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
749
750 left &= reg_mask;
751 right &= reg_mask;
752 uint64_t result = (left + right + carry_in) & reg_mask;
753
754 if (set_flags) {
755 ReadNzcv().SetN(CalcNFlag(result, reg_size));
756 ReadNzcv().SetZ(CalcZFlag(result));
757
758 // Compute the C flag by comparing the result to the max unsigned integer.
759 uint64_t max_uint_2op = max_uint - carry_in;
760 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
761 ReadNzcv().SetC(C ? 1 : 0);
762
763 // Overflow iff the sign bit is the same for the two inputs and different
764 // for the result.
765 uint64_t left_sign = left & sign_mask;
766 uint64_t right_sign = right & sign_mask;
767 uint64_t result_sign = result & sign_mask;
768 bool V = (left_sign == right_sign) && (left_sign != result_sign);
769 ReadNzcv().SetV(V ? 1 : 0);
770
771 LogSystemRegister(NZCV);
772 }
773 return result;
774}
775
776
777int64_t Simulator::ShiftOperand(unsigned reg_size,
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000778 uint64_t uvalue,
Alexandre Ramesd3832962016-07-04 15:03:43 +0100779 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100780 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800781 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
782 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000783 if (amount > 0) {
784 uint64_t mask = GetUintMask(reg_size);
785 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
786 // The behavior is undefined in c++ if the shift amount greater than or
787 // equal to the register lane size. Work out the shifted result based on
788 // architectural behavior before performing the c++ type shfit operations.
789 switch (shift_type) {
790 case LSL:
791 if (amount >= reg_size) {
792 return UINT64_C(0);
793 }
794 uvalue <<= amount;
795 break;
796 case LSR:
797 if (amount >= reg_size) {
798 return UINT64_C(0);
799 }
800 uvalue >>= amount;
801 break;
802 case ASR:
803 if (amount >= reg_size) {
804 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
805 }
806 uvalue >>= amount;
807 if (is_negative) {
808 // Simulate sign-extension to 64 bits.
809 uvalue |= ~UINT64_C(0) << (reg_size - amount);
810 }
811 break;
812 case ROR: {
813 uvalue = RotateRight(uvalue, amount, reg_size);
814 break;
TatWai Chong29a0c432019-11-06 22:20:44 -0800815 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000816 default:
817 VIXL_UNIMPLEMENTED();
818 return 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100819 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000820 uvalue &= mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100821 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000822
823 int64_t result;
824 memcpy(&result, &uvalue, sizeof(result));
825 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100826}
827
828
829int64_t Simulator::ExtendValue(unsigned reg_size,
830 int64_t value,
831 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100832 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100833 switch (extend_type) {
834 case UXTB:
835 value &= kByteMask;
836 break;
837 case UXTH:
838 value &= kHalfWordMask;
839 break;
840 case UXTW:
841 value &= kWordMask;
842 break;
843 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000844 value &= kByteMask;
845 if ((value & 0x80) != 0) {
846 value |= ~UINT64_C(0) << 8;
847 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100848 break;
849 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000850 value &= kHalfWordMask;
851 if ((value & 0x8000) != 0) {
852 value |= ~UINT64_C(0) << 16;
853 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100854 break;
855 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000856 value &= kWordMask;
857 if ((value & 0x80000000) != 0) {
858 value |= ~UINT64_C(0) << 32;
859 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100860 break;
861 case UXTX:
862 case SXTX:
863 break;
864 default:
865 VIXL_UNREACHABLE();
866 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000867 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100868}
869
870
871void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
872 AssertSupportedFPCR();
873
874 // TODO: This assumes that the C++ implementation handles comparisons in the
875 // way that we expect (as per AssertSupportedFPCR()).
876 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100877 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100878 ReadNzcv().SetRawValue(FPUnorderedFlag);
879 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
880 (trap == EnableTrap)) {
881 process_exception = true;
882 }
883 } else if (val0 < val1) {
884 ReadNzcv().SetRawValue(FPLessThanFlag);
885 } else if (val0 > val1) {
886 ReadNzcv().SetRawValue(FPGreaterThanFlag);
887 } else if (val0 == val1) {
888 ReadNzcv().SetRawValue(FPEqualFlag);
889 } else {
890 VIXL_UNREACHABLE();
891 }
892 LogSystemRegister(NZCV);
893 if (process_exception) FPProcessException();
894}
895
896
Alexandre Rames868bfc42016-07-19 17:10:48 +0100897uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
898 VIXL_ASSERT(mem_op.IsValid());
899 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
900 if (mem_op.IsImmediateOffset()) {
901 return base + mem_op.GetOffset();
902 } else {
903 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
904 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100905 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100906 if (mem_op.GetShift() != NO_SHIFT) {
907 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
908 }
909 if (mem_op.GetExtend() != NO_EXTEND) {
910 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
911 }
912 return static_cast<uint64_t>(base + offset);
913 }
914}
915
916
Alexandre Ramesd3832962016-07-04 15:03:43 +0100917Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
918 unsigned reg_size, unsigned lane_size) {
919 VIXL_ASSERT(reg_size >= lane_size);
920
921 uint32_t format = 0;
922 if (reg_size != lane_size) {
923 switch (reg_size) {
924 default:
925 VIXL_UNREACHABLE();
926 break;
927 case kQRegSizeInBytes:
928 format = kPrintRegAsQVector;
929 break;
930 case kDRegSizeInBytes:
931 format = kPrintRegAsDVector;
932 break;
933 }
934 }
935
936 switch (lane_size) {
937 default:
938 VIXL_UNREACHABLE();
939 break;
940 case kQRegSizeInBytes:
941 format |= kPrintReg1Q;
942 break;
943 case kDRegSizeInBytes:
944 format |= kPrintReg1D;
945 break;
946 case kSRegSizeInBytes:
947 format |= kPrintReg1S;
948 break;
949 case kHRegSizeInBytes:
950 format |= kPrintReg1H;
951 break;
952 case kBRegSizeInBytes:
953 format |= kPrintReg1B;
954 break;
955 }
956 // These sizes would be duplicate case labels.
957 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
958 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
959 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
960 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
961
962 return static_cast<PrintRegisterFormat>(format);
963}
964
965
966Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
967 VectorFormat vform) {
968 switch (vform) {
969 default:
970 VIXL_UNREACHABLE();
971 return kPrintReg16B;
972 case kFormat16B:
973 return kPrintReg16B;
974 case kFormat8B:
975 return kPrintReg8B;
976 case kFormat8H:
977 return kPrintReg8H;
978 case kFormat4H:
979 return kPrintReg4H;
980 case kFormat4S:
981 return kPrintReg4S;
982 case kFormat2S:
983 return kPrintReg2S;
984 case kFormat2D:
985 return kPrintReg2D;
986 case kFormat1D:
987 return kPrintReg1D;
988
989 case kFormatB:
990 return kPrintReg1B;
991 case kFormatH:
992 return kPrintReg1H;
993 case kFormatS:
994 return kPrintReg1S;
995 case kFormatD:
996 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100997
998 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000999 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +01001000 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001001 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +01001002 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001003 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +01001004 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001005 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001006 }
1007}
1008
1009
1010Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1011 VectorFormat vform) {
1012 switch (vform) {
1013 default:
1014 VIXL_UNREACHABLE();
1015 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001016 case kFormat8H:
1017 return kPrintReg8HFP;
1018 case kFormat4H:
1019 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001020 case kFormat4S:
1021 return kPrintReg4SFP;
1022 case kFormat2S:
1023 return kPrintReg2SFP;
1024 case kFormat2D:
1025 return kPrintReg2DFP;
1026 case kFormat1D:
1027 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001028 case kFormatH:
1029 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001030 case kFormatS:
1031 return kPrintReg1SFP;
1032 case kFormatD:
1033 return kPrintReg1DFP;
1034 }
1035}
1036
Jacob Bramley423e5422019-11-13 19:15:55 +00001037void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001038 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +00001039 if (i == kSpRegCode) i = kSPRegInternalCode;
1040 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001041 }
1042}
1043
Jacob Bramley423e5422019-11-13 19:15:55 +00001044void Simulator::PrintVRegisters() {
1045 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1046 PrintVRegister(i);
1047 }
1048}
1049
1050void Simulator::PrintZRegisters() {
1051 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
1052 PrintZRegister(i);
1053 }
1054}
1055
1056void Simulator::PrintWrittenRegisters() {
1057 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1058 if (registers_[i].WrittenSinceLastLog()) {
1059 if (i == kSpRegCode) i = kSPRegInternalCode;
1060 PrintRegister(i);
1061 }
1062 }
1063}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001064
1065void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001066 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001067 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001068 if (vregisters_[i].WrittenSinceLastLog()) {
1069 // Z registers are initialised in the constructor before the user can
1070 // configure the CPU features, so we must also check for SVE here.
1071 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
1072 PrintZRegister(i);
1073 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00001074 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001075 }
1076 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001077 }
1078}
1079
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001080void Simulator::PrintWrittenPRegisters() {
1081 // P registers are initialised in the constructor before the user can
1082 // configure the CPU features, so we must check for SVE here.
1083 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
1084 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
1085 if (pregisters_[i].WrittenSinceLastLog()) {
1086 PrintPRegister(i);
1087 }
1088 }
Jacob Bramley0d754e92020-06-18 10:59:09 +01001089 if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001090}
1091
Alexandre Ramesd3832962016-07-04 15:03:43 +01001092void Simulator::PrintSystemRegisters() {
1093 PrintSystemRegister(NZCV);
1094 PrintSystemRegister(FPCR);
1095}
1096
Jacob Bramley423e5422019-11-13 19:15:55 +00001097void Simulator::PrintRegisterValue(const uint8_t* value,
1098 int value_size,
1099 PrintRegisterFormat format) {
1100 int print_width = GetPrintRegSizeInBytes(format);
1101 VIXL_ASSERT(print_width <= value_size);
1102 for (int i = value_size - 1; i >= print_width; i--) {
1103 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +01001104 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +00001105 // If we aren't explicitly printing a partial value, ensure that the
1106 // unprinted bits are zero.
1107 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001108 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001109 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +00001110 for (int i = print_width - 1; i >= 0; i--) {
1111 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001112 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001113}
1114
Jacob Bramley423e5422019-11-13 19:15:55 +00001115void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
1116 uint16_t lane_mask,
1117 PrintRegisterFormat format) {
1118 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
1119 int lane_size = GetPrintRegLaneSizeInBytes(format);
1120 fprintf(stream_, " (");
1121 bool last_inactive = false;
1122 const char* sep = "";
1123 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
1124 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
1125 if (access) {
1126 // Read the lane as a double, so we can format all FP types in the same
1127 // way. We squash NaNs, and a double can exactly represent any other value
1128 // that the smaller types can represent, so this is lossless.
1129 double element;
1130 switch (lane_size) {
1131 case kHRegSizeInBytes: {
1132 Float16 element_fp16;
1133 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
1134 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
1135 element = FPToDouble(element_fp16, kUseDefaultNaN);
1136 break;
1137 }
1138 case kSRegSizeInBytes: {
1139 float element_fp32;
1140 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
1141 element = static_cast<double>(element_fp32);
1142 break;
1143 }
1144 case kDRegSizeInBytes: {
1145 memcpy(&element, &value[i * lane_size], sizeof(element));
1146 break;
1147 }
1148 default:
1149 VIXL_UNREACHABLE();
1150 fprintf(stream_, "{UnknownFPValue}");
1151 continue;
1152 }
1153 if (IsNaN(element)) {
1154 // The fprintf behaviour for NaNs is implementation-defined. Always
1155 // print "nan", so that traces are consistent.
1156 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
1157 } else {
1158 fprintf(stream_,
1159 "%s%s%#.4g%s",
1160 sep,
1161 clr_vreg_value,
1162 element,
1163 clr_normal);
1164 }
1165 last_inactive = false;
1166 } else if (!last_inactive) {
1167 // Replace each contiguous sequence of inactive lanes with "...".
1168 fprintf(stream_, "%s...", sep);
1169 last_inactive = true;
1170 }
1171 }
1172 fprintf(stream_, ")");
1173}
1174
1175void Simulator::PrintRegister(int code,
1176 PrintRegisterFormat format,
1177 const char* suffix) {
1178 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
1179 (static_cast<unsigned>(code) == kSPRegInternalCode));
1180 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
1181 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
1182
1183 SimRegister* reg;
1184 SimRegister zero;
1185 if (code == kZeroRegCode) {
1186 reg = &zero;
1187 } else {
1188 // registers_[31] holds the SP.
1189 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1190 reg = &registers_[code % kNumberOfRegisters];
1191 }
1192
1193 // We trace register writes as whole register values, implying that any
1194 // unprinted bits are all zero:
1195 // "# x{code}: 0x{-----value----}"
1196 // "# w{code}: 0x{-value}"
1197 // Stores trace partial register values, implying nothing about the unprinted
1198 // bits:
1199 // "# x{code}<63:0>: 0x{-----value----}"
1200 // "# x{code}<31:0>: 0x{-value}"
1201 // "# x{code}<15:0>: 0x{--}"
1202 // "# x{code}<7:0>: 0x{}"
1203
1204 bool is_partial = (format & kPrintRegPartial) != 0;
1205 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1206 std::stringstream name;
1207 if (is_partial) {
1208 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
1209 } else {
1210 // Notify the register that it has been logged, but only if we're printing
1211 // all of it.
1212 reg->NotifyRegisterLogged();
1213 switch (print_reg_size) {
1214 case kWRegSize:
1215 name << WRegNameForCode(code);
1216 break;
1217 case kXRegSize:
1218 name << XRegNameForCode(code);
1219 break;
1220 default:
1221 VIXL_UNREACHABLE();
1222 return;
1223 }
1224 }
1225
1226 fprintf(stream_,
1227 "# %s%*s: %s",
1228 clr_reg_name,
1229 kPrintRegisterNameFieldWidth,
1230 name.str().c_str(),
1231 clr_reg_value);
1232 PrintRegisterValue(*reg, format);
1233 fprintf(stream_, "%s%s", clr_normal, suffix);
1234}
1235
1236void Simulator::PrintVRegister(int code,
1237 PrintRegisterFormat format,
1238 const char* suffix) {
1239 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
1240 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
1241 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
1242 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
1243
1244 // We trace register writes as whole register values, implying that any
1245 // unprinted bits are all zero:
1246 // "# v{code}: 0x{-------------value------------}"
1247 // "# d{code}: 0x{-----value----}"
1248 // "# s{code}: 0x{-value}"
1249 // "# h{code}: 0x{--}"
1250 // "# b{code}: 0x{}"
1251 // Stores trace partial register values, implying nothing about the unprinted
1252 // bits:
1253 // "# v{code}<127:0>: 0x{-------------value------------}"
1254 // "# v{code}<63:0>: 0x{-----value----}"
1255 // "# v{code}<31:0>: 0x{-value}"
1256 // "# v{code}<15:0>: 0x{--}"
1257 // "# v{code}<7:0>: 0x{}"
1258
1259 bool is_partial = ((format & kPrintRegPartial) != 0);
1260 std::stringstream name;
1261 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1262 if (is_partial) {
1263 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1264 } else {
1265 // Notify the register that it has been logged, but only if we're printing
1266 // all of it.
1267 vregisters_[code].NotifyRegisterLogged();
1268 switch (print_reg_size) {
1269 case kBRegSize:
1270 name << BRegNameForCode(code);
1271 break;
1272 case kHRegSize:
1273 name << HRegNameForCode(code);
1274 break;
1275 case kSRegSize:
1276 name << SRegNameForCode(code);
1277 break;
1278 case kDRegSize:
1279 name << DRegNameForCode(code);
1280 break;
1281 case kQRegSize:
1282 name << VRegNameForCode(code);
1283 break;
1284 default:
1285 VIXL_UNREACHABLE();
1286 return;
1287 }
1288 }
1289
1290 fprintf(stream_,
1291 "# %s%*s: %s",
1292 clr_vreg_name,
1293 kPrintRegisterNameFieldWidth,
1294 name.str().c_str(),
1295 clr_vreg_value);
1296 PrintRegisterValue(vregisters_[code], format);
1297 fprintf(stream_, "%s", clr_normal);
1298 if ((format & kPrintRegAsFP) != 0) {
1299 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1300 }
1301 fprintf(stream_, "%s", suffix);
1302}
1303
1304void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1305 int reg_count,
1306 uint16_t focus_mask,
1307 PrintRegisterFormat format) {
1308 bool print_fp = (format & kPrintRegAsFP) != 0;
1309 // Suppress FP formatting, so we can specify the lanes we're interested in.
1310 PrintRegisterFormat format_no_fp =
1311 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1312
1313 for (int r = 0; r < reg_count; r++) {
1314 int code = (rt_code + r) % kNumberOfVRegisters;
1315 PrintVRegister(code, format_no_fp, "");
1316 if (print_fp) {
1317 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1318 }
1319 fprintf(stream_, "\n");
1320 }
1321}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001322
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001323void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1324 int q_index,
1325 int reg_count,
1326 uint16_t focus_mask,
1327 PrintRegisterFormat format) {
1328 bool print_fp = (format & kPrintRegAsFP) != 0;
1329 // Suppress FP formatting, so we can specify the lanes we're interested in.
1330 PrintRegisterFormat format_no_fp =
1331 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001332
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001333 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001334
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001335 const unsigned size = kQRegSizeInBytes;
1336 unsigned byte_index = q_index * size;
1337 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1338 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001339
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001340 for (int r = 0; r < reg_count; r++) {
1341 int code = (rt_code + r) % kNumberOfZRegisters;
1342 PrintPartialZRegister(code, q_index, format_no_fp, "");
1343 if (print_fp) {
1344 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001345 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001346 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001347 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001348}
1349
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001350void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1351 // We're going to print the register in parts, so force a partial format.
1352 format = GetPrintRegPartial(format);
1353 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1354 int vl = GetVectorLengthInBits();
1355 VIXL_ASSERT((vl % kQRegSize) == 0);
1356 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1357 PrintPartialZRegister(code, i, format);
1358 }
1359 vregisters_[code].NotifyRegisterLogged();
1360}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001361
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001362void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1363 // We're going to print the register in parts, so force a partial format.
1364 format = GetPrintRegPartial(format);
1365 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1366 int vl = GetVectorLengthInBits();
1367 VIXL_ASSERT((vl % kQRegSize) == 0);
1368 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1369 PrintPartialPRegister(code, i, format);
1370 }
1371 pregisters_[code].NotifyRegisterLogged();
1372}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001373
Jacob Bramley0d754e92020-06-18 10:59:09 +01001374void Simulator::PrintFFR(PrintRegisterFormat format) {
1375 // We're going to print the register in parts, so force a partial format.
1376 format = GetPrintRegPartial(format);
1377 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1378 int vl = GetVectorLengthInBits();
1379 VIXL_ASSERT((vl % kQRegSize) == 0);
1380 SimPRegister& ffr = ReadFFR();
1381 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1382 PrintPartialPRegister("FFR", ffr, i, format);
1383 }
1384 ffr.NotifyRegisterLogged();
1385}
1386
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001387void Simulator::PrintPartialZRegister(int code,
1388 int q_index,
1389 PrintRegisterFormat format,
1390 const char* suffix) {
1391 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1392 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1393 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1394 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001395
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001396 // We _only_ trace partial Z register values in Q-sized chunks, because
1397 // they're often too large to reasonably fit on a single line. Each line
1398 // implies nothing about the unprinted bits.
1399 // "# z{code}<127:0>: 0x{-------------value------------}"
1400
1401 format = GetPrintRegAsQChunkOfSVE(format);
1402
1403 const unsigned size = kQRegSizeInBytes;
1404 unsigned byte_index = q_index * size;
1405 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1406 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1407
1408 int lsb = q_index * kQRegSize;
1409 int msb = lsb + kQRegSize - 1;
1410 std::stringstream name;
1411 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001412
1413 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001414 "# %s%*s: %s",
1415 clr_vreg_name,
1416 kPrintRegisterNameFieldWidth,
1417 name.str().c_str(),
1418 clr_vreg_value);
1419 PrintRegisterValue(value, size, format);
1420 fprintf(stream_, "%s", clr_normal);
1421 if ((format & kPrintRegAsFP) != 0) {
1422 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1423 }
1424 fprintf(stream_, "%s", suffix);
1425}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001426
Jacob Bramley0d754e92020-06-18 10:59:09 +01001427void Simulator::PrintPartialPRegister(const char* name,
1428 const SimPRegister& reg,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001429 int q_index,
1430 PrintRegisterFormat format,
1431 const char* suffix) {
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001432 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1433 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1434 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1435
1436 // We don't currently use the format for anything here.
1437 USE(format);
1438
1439 // We _only_ trace partial P register values, because they're often too large
1440 // to reasonably fit on a single line. Each line implies nothing about the
1441 // unprinted bits.
1442 //
1443 // We print values in binary, with spaces between each bit, in order for the
1444 // bits to align with the Z register bytes that they predicate.
Jacob Bramley0d754e92020-06-18 10:59:09 +01001445 // "# {name}<15:0>: 0b{-------------value------------}"
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001446
1447 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1448 int lsb = q_index * print_size_in_bits;
1449 int msb = lsb + print_size_in_bits - 1;
Jacob Bramley0d754e92020-06-18 10:59:09 +01001450 std::stringstream prefix;
1451 prefix << name << '<' << msb << ':' << lsb << '>';
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001452
1453 fprintf(stream_,
1454 "# %s%*s: %s0b",
1455 clr_preg_name,
1456 kPrintRegisterNameFieldWidth,
Jacob Bramley0d754e92020-06-18 10:59:09 +01001457 prefix.str().c_str(),
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001458 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001459 for (int i = msb; i >= lsb; i--) {
Jacob Bramley0d754e92020-06-18 10:59:09 +01001460 fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001461 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001462 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001463}
1464
Jacob Bramley0d754e92020-06-18 10:59:09 +01001465void Simulator::PrintPartialPRegister(int code,
1466 int q_index,
1467 PrintRegisterFormat format,
1468 const char* suffix) {
1469 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1470 PrintPartialPRegister(PRegNameForCode(code),
1471 pregisters_[code],
1472 q_index,
1473 format,
1474 suffix);
1475}
1476
Alexandre Ramesd3832962016-07-04 15:03:43 +01001477void Simulator::PrintSystemRegister(SystemRegister id) {
1478 switch (id) {
1479 case NZCV:
1480 fprintf(stream_,
1481 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1482 clr_flag_name,
1483 clr_flag_value,
1484 ReadNzcv().GetN(),
1485 ReadNzcv().GetZ(),
1486 ReadNzcv().GetC(),
1487 ReadNzcv().GetV(),
1488 clr_normal);
1489 break;
1490 case FPCR: {
1491 static const char* rmode[] = {"0b00 (Round to Nearest)",
1492 "0b01 (Round towards Plus Infinity)",
1493 "0b10 (Round towards Minus Infinity)",
1494 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001495 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001496 fprintf(stream_,
1497 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1498 clr_flag_name,
1499 clr_flag_value,
1500 ReadFpcr().GetAHP(),
1501 ReadFpcr().GetDN(),
1502 ReadFpcr().GetFZ(),
1503 rmode[ReadFpcr().GetRMode()],
1504 clr_normal);
1505 break;
1506 }
1507 default:
1508 VIXL_UNREACHABLE();
1509 }
1510}
1511
Jacob Bramley423e5422019-11-13 19:15:55 +00001512uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1513 uint16_t future_access_mask,
1514 int struct_element_count,
1515 int lane_size_in_bytes,
1516 const char* op,
1517 uintptr_t address,
1518 int reg_size_in_bytes) {
1519 // We want to assume that we'll access at least one lane.
1520 VIXL_ASSERT(access_mask != 0);
1521 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1522 (reg_size_in_bytes == kQRegSizeInBytes));
1523 bool started_annotation = false;
1524 // Indent to match the register field, the fixed formatting, and the value
1525 // prefix ("0x"): "# {name}: 0x"
1526 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1527 // First, annotate the lanes (byte by byte).
1528 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1529 bool access = (access_mask & (1 << lane)) != 0;
1530 bool future = (future_access_mask & (1 << lane)) != 0;
1531 if (started_annotation) {
1532 // If we've started an annotation, draw a horizontal line in addition to
1533 // any other symbols.
1534 if (access) {
1535 fprintf(stream_, "─╨");
1536 } else if (future) {
1537 fprintf(stream_, "─║");
1538 } else {
1539 fprintf(stream_, "──");
1540 }
1541 } else {
1542 if (access) {
1543 started_annotation = true;
1544 fprintf(stream_, " â•™");
1545 } else if (future) {
1546 fprintf(stream_, " â•‘");
1547 } else {
1548 fprintf(stream_, " ");
1549 }
1550 }
1551 }
1552 VIXL_ASSERT(started_annotation);
1553 fprintf(stream_, "─ 0x");
1554 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1555 // Print the most-significant struct element first.
1556 const char* sep = "";
1557 for (int i = struct_element_count - 1; i >= 0; i--) {
1558 int offset = lane_size_in_bytes * i;
1559 uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset);
1560 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1561 sep = "'";
1562 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001563 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001564 " %s %s0x%016" PRIxPTR "%s\n",
1565 op,
1566 clr_memory_address,
1567 address,
1568 clr_normal);
1569 return future_access_mask & ~access_mask;
1570}
1571
1572void Simulator::PrintAccess(int code,
1573 PrintRegisterFormat format,
1574 const char* op,
1575 uintptr_t address) {
1576 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1577 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1578 if ((format & kPrintRegPartial) == 0) {
1579 registers_[code].NotifyRegisterLogged();
1580 }
1581 // Scalar-format accesses use a simple format:
1582 // "# {reg}: 0x{value} -> {address}"
1583
1584 // Suppress the newline, so the access annotation goes on the same line.
1585 PrintRegister(code, format, "");
1586 fprintf(stream_,
1587 " %s %s0x%016" PRIxPTR "%s\n",
1588 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001589 clr_memory_address,
1590 address,
1591 clr_normal);
1592}
1593
Jacob Bramley423e5422019-11-13 19:15:55 +00001594void Simulator::PrintVAccess(int code,
1595 PrintRegisterFormat format,
1596 const char* op,
1597 uintptr_t address) {
1598 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001599
Jacob Bramley423e5422019-11-13 19:15:55 +00001600 // Scalar-format accesses use a simple format:
1601 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001602
Jacob Bramley423e5422019-11-13 19:15:55 +00001603 // Suppress the newline, so the access annotation goes on the same line.
1604 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001605 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001606 " %s %s0x%016" PRIxPTR "%s\n",
1607 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001608 clr_memory_address,
1609 address,
1610 clr_normal);
1611}
1612
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001613void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001614 int reg_count,
1615 PrintRegisterFormat format,
1616 const char* op,
1617 uintptr_t address) {
1618 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1619
1620 // For example:
1621 // "# v{code}: 0x{value}"
1622 // "# ...: 0x{value}"
1623 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1624 // "# ╙───── {struct_value} -> {highest_address}"
1625
1626 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001627 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001628
1629 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1630 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1631 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1632 uint16_t access_mask = 1 << i;
1633 VIXL_ASSERT((lane_mask & access_mask) != 0);
1634 lane_mask = PrintPartialAccess(access_mask,
1635 lane_mask,
1636 reg_count,
1637 lane_size_in_bytes,
1638 op,
1639 address + (i * reg_count));
1640 }
1641}
1642
1643void Simulator::PrintVSingleStructAccess(int rt_code,
1644 int reg_count,
1645 int lane,
1646 PrintRegisterFormat format,
1647 const char* op,
1648 uintptr_t address) {
1649 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1650
1651 // For example:
1652 // "# v{code}: 0x{value}"
1653 // "# ...: 0x{value}"
1654 // "# ╙───── {struct_value} -> {address}"
1655
1656 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1657 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1658 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1659 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1660}
1661
1662void Simulator::PrintVReplicatingStructAccess(int rt_code,
1663 int reg_count,
1664 PrintRegisterFormat format,
1665 const char* op,
1666 uintptr_t address) {
1667 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1668
1669 // For example:
1670 // "# v{code}: 0x{value}"
1671 // "# ...: 0x{value}"
1672 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1673
1674 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1675 uint16_t lane_mask = GetPrintRegLaneMask(format);
1676 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1677 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1678}
1679
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001680void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1681 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1682
1683 // Scalar-format accesses are split into separate chunks, each of which uses a
1684 // simple format:
1685 // "# z{code}<127:0>: 0x{value} -> {address}"
1686 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1687 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1688 // etc
1689
1690 int vl = GetVectorLengthInBits();
1691 VIXL_ASSERT((vl % kQRegSize) == 0);
1692 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1693 // Suppress the newline, so the access annotation goes on the same line.
1694 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1695 fprintf(stream_,
1696 " %s %s0x%016" PRIxPTR "%s\n",
1697 op,
1698 clr_memory_address,
1699 address,
1700 clr_normal);
1701 address += kQRegSizeInBytes;
1702 }
1703}
1704
1705void Simulator::PrintZStructAccess(int rt_code,
1706 int reg_count,
1707 const LogicPRegister& pg,
1708 PrintRegisterFormat format,
1709 int msize_in_bytes,
1710 const char* op,
1711 const LogicSVEAddressVector& addr) {
1712 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1713
1714 // For example:
1715 // "# z{code}<255:128>: 0x{value}"
1716 // "# ...<255:128>: 0x{value}"
1717 // "# ║ ╙─ {struct_value} -> {first_address}"
1718 // "# ╙───── {struct_value} -> {last_address}"
1719
1720 // We're going to print the register in parts, so force a partial format.
1721 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1722 format = GetPrintRegPartial(format);
1723
1724 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1725 int vl = GetVectorLengthInBits();
1726 VIXL_ASSERT((vl % kQRegSize) == 0);
1727 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1728 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1729 uint16_t pred =
1730 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1731 if ((pred == 0) && skip_inactive_chunks) continue;
1732
1733 PrintZRegistersForStructuredAccess(rt_code,
1734 q_index,
1735 reg_count,
1736 pred,
1737 format);
1738 if (pred == 0) {
1739 // This register chunk has no active lanes. The loop below would print
1740 // nothing, so leave a blank line to keep structures grouped together.
1741 fprintf(stream_, "#\n");
1742 continue;
1743 }
1744 for (int i = 0; i < lanes_per_q; i++) {
1745 uint16_t access = 1 << (i * esize_in_bytes);
1746 int lane = (q_index * lanes_per_q) + i;
1747 // Skip inactive lanes.
1748 if ((pred & access) == 0) continue;
1749 pred = PrintPartialAccess(access,
1750 pred,
1751 reg_count,
1752 msize_in_bytes,
1753 op,
1754 addr.GetStructAddress(lane));
1755 }
1756 }
1757
1758 // We print the whole register, even for stores.
1759 for (int i = 0; i < reg_count; i++) {
1760 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1761 }
1762}
1763
1764void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1765 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1766
1767 // Scalar-format accesses are split into separate chunks, each of which uses a
1768 // simple format:
1769 // "# p{code}<15:0>: 0b{value} -> {address}"
1770 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1771 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1772 // etc
1773
1774 int vl = GetVectorLengthInBits();
1775 VIXL_ASSERT((vl % kQRegSize) == 0);
1776 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1777 // Suppress the newline, so the access annotation goes on the same line.
1778 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1779 fprintf(stream_,
1780 " %s %s0x%016" PRIxPTR "%s\n",
1781 op,
1782 clr_memory_address,
1783 address,
1784 clr_normal);
1785 address += kQRegSizeInBytes;
1786 }
1787}
1788
Jacob Bramley423e5422019-11-13 19:15:55 +00001789void Simulator::PrintRead(int rt_code,
1790 PrintRegisterFormat format,
1791 uintptr_t address) {
1792 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1793 registers_[rt_code].NotifyRegisterLogged();
1794 PrintAccess(rt_code, format, "<-", address);
1795}
1796
1797void Simulator::PrintExtendingRead(int rt_code,
1798 PrintRegisterFormat format,
1799 int access_size_in_bytes,
1800 uintptr_t address) {
1801 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1802 if (access_size_in_bytes == reg_size_in_bytes) {
1803 // There is no extension here, so print a simple load.
1804 PrintRead(rt_code, format, address);
1805 return;
1806 }
1807 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1808
1809 // For sign- and zero-extension, make it clear that the resulting register
1810 // value is different from what is loaded from memory.
1811 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1812 registers_[rt_code].NotifyRegisterLogged();
1813 PrintRegister(rt_code, format);
1814 PrintPartialAccess(1,
1815 0,
1816 1,
1817 access_size_in_bytes,
1818 "<-",
1819 address,
1820 kXRegSizeInBytes);
1821}
1822
1823void Simulator::PrintVRead(int rt_code,
1824 PrintRegisterFormat format,
1825 uintptr_t address) {
1826 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1827 vregisters_[rt_code].NotifyRegisterLogged();
1828 PrintVAccess(rt_code, format, "<-", address);
1829}
1830
Jacob Bramley423e5422019-11-13 19:15:55 +00001831void Simulator::PrintWrite(int rt_code,
1832 PrintRegisterFormat format,
1833 uintptr_t address) {
1834 // Because this trace doesn't represent a change to the source register's
1835 // value, only print the relevant part of the value.
1836 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001837 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001838 registers_[rt_code].NotifyRegisterLogged();
1839 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001840}
1841
Jacob Bramley423e5422019-11-13 19:15:55 +00001842void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001843 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001844 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001845 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001846 // value, only print the relevant part of the value.
1847 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001848 // It only makes sense to write scalar values here. Vectors are handled by
1849 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001850 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001851 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001852}
1853
Jacob Bramleye79723a2016-06-07 17:50:47 +01001854void Simulator::PrintTakenBranch(const Instruction* target) {
1855 fprintf(stream_,
1856 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1857 clr_branch_marker,
1858 clr_normal,
1859 reinterpret_cast<uint64_t>(target));
1860}
1861
Alexandre Ramesd3832962016-07-04 15:03:43 +01001862// Visitors---------------------------------------------------------------------
1863
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001864
Martyn Capewell8c691852020-07-15 18:33:15 +01001865void Simulator::Visit(Metadata* metadata, const Instruction* instr) {
1866 VIXL_ASSERT(metadata->count("form") > 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001867 std::string form = (*metadata)["form"];
Martyn Capewell8c691852020-07-15 18:33:15 +01001868 if ((form_to_visitor_.count(form) > 0) && form_to_visitor_[form]) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01001869 form_hash_ = Hash(form.c_str());
Martyn Capewell8c691852020-07-15 18:33:15 +01001870 form_to_visitor_[form](this, instr);
1871 } else {
1872 VisitUnimplemented(instr);
1873 }
1874}
1875
Martyn Capewell6bf28752020-08-05 11:57:06 +01001876void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell51643312020-08-24 15:58:57 +01001877 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01001878 SimPRegister& pd = ReadPRegister(instr->GetPd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001879 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001880 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001881 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001882
1883 switch (form_hash_) {
1884 case Hash("match_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001885 match(vform, pd, zn, zm, /* negate_match = */ false);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001886 break;
1887 case Hash("nmatch_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001888 match(vform, pd, zn, zm, /* negate_match = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001889 break;
1890 default:
1891 VIXL_UNIMPLEMENTED();
1892 }
Martyn Capewell51643312020-08-24 15:58:57 +01001893 mov_zeroing(pd, pg, pd);
1894 PredTest(vform, pg, pd);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001895}
1896
1897void Simulator::Simulate_PdT_Rn_Rm(const Instruction* instr) {
1898 SimPRegister& pd = ReadPRegister(instr->GetPd());
1899 USE(pd);
1900
1901 switch (form_hash_) {
1902 case Hash("whilege_p_p_rr"):
1903 VIXL_UNIMPLEMENTED();
1904 break;
1905 case Hash("whilegt_p_p_rr"):
1906 VIXL_UNIMPLEMENTED();
1907 break;
1908 case Hash("whilehi_p_p_rr"):
1909 VIXL_UNIMPLEMENTED();
1910 break;
1911 case Hash("whilehs_p_p_rr"):
1912 VIXL_UNIMPLEMENTED();
1913 break;
1914 default:
1915 VIXL_UNIMPLEMENTED();
1916 }
1917}
1918
1919void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {
1920 SimPRegister& pd = ReadPRegister(instr->GetPd());
1921 USE(pd);
1922
1923 switch (form_hash_) {
1924 case Hash("whilerw_p_rr"):
1925 VIXL_UNIMPLEMENTED();
1926 break;
1927 case Hash("whilewr_p_rr"):
1928 VIXL_UNIMPLEMENTED();
1929 break;
1930 default:
1931 VIXL_UNIMPLEMENTED();
1932 }
1933}
1934
1935void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
1936 SimVRegister& zd = ReadVRegister(instr->GetRd());
1937 USE(zd);
1938 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
1939 USE(zn1);
1940
1941 switch (form_hash_) {
1942 case Hash("ext_z_zi_con"):
1943 VIXL_UNIMPLEMENTED();
1944 break;
1945 default:
1946 VIXL_UNIMPLEMENTED();
1947 }
1948}
1949
1950void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
1951 SimVRegister& zd = ReadVRegister(instr->GetRd());
1952 USE(zd);
1953 SimVRegister& zm = ReadVRegister(instr->GetRm());
1954 USE(zm);
1955 SimVRegister& zn = ReadVRegister(instr->GetRn());
1956 USE(zn);
1957
1958 switch (form_hash_) {
1959 case Hash("histseg_z_zz"):
1960 VIXL_UNIMPLEMENTED();
1961 break;
1962 case Hash("pmul_z_zz"):
1963 VIXL_UNIMPLEMENTED();
1964 break;
1965 default:
1966 VIXL_UNIMPLEMENTED();
1967 }
1968}
1969
1970void Simulator::Simulate_ZdD_PgM_ZnS(const Instruction* instr) {
1971 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
1972 USE(pg);
1973 SimVRegister& zd = ReadVRegister(instr->GetRd());
1974 USE(zd);
1975 SimVRegister& zn = ReadVRegister(instr->GetRn());
1976 USE(zn);
1977
1978 switch (form_hash_) {
1979 case Hash("fcvtlt_z_p_z_s2d"):
1980 VIXL_UNIMPLEMENTED();
1981 break;
1982 default:
1983 VIXL_UNIMPLEMENTED();
1984 }
1985}
1986
1987void Simulator::Simulate_ZdD_ZnD_ZmD_imm(const Instruction* instr) {
1988 SimVRegister& zd = ReadVRegister(instr->GetRd());
1989 USE(zd);
1990 SimVRegister& zn = ReadVRegister(instr->GetRn());
1991 USE(zn);
1992
1993 switch (form_hash_) {
1994 case Hash("mul_z_zzi_d"):
1995 VIXL_UNIMPLEMENTED();
1996 break;
1997 case Hash("sqdmulh_z_zzi_d"):
1998 VIXL_UNIMPLEMENTED();
1999 break;
2000 case Hash("sqrdmulh_z_zzi_d"):
2001 VIXL_UNIMPLEMENTED();
2002 break;
2003 default:
2004 VIXL_UNIMPLEMENTED();
2005 }
2006}
2007
2008void Simulator::Simulate_ZdD_ZnS_ZmS_imm(const Instruction* instr) {
2009 SimVRegister& zd = ReadVRegister(instr->GetRd());
2010 USE(zd);
2011 SimVRegister& zn = ReadVRegister(instr->GetRn());
2012 USE(zn);
2013
2014 switch (form_hash_) {
2015 case Hash("smullb_z_zzi_d"):
2016 VIXL_UNIMPLEMENTED();
2017 break;
2018 case Hash("smullt_z_zzi_d"):
2019 VIXL_UNIMPLEMENTED();
2020 break;
2021 case Hash("sqdmullb_z_zzi_d"):
2022 VIXL_UNIMPLEMENTED();
2023 break;
2024 case Hash("sqdmullt_z_zzi_d"):
2025 VIXL_UNIMPLEMENTED();
2026 break;
2027 case Hash("umullb_z_zzi_d"):
2028 VIXL_UNIMPLEMENTED();
2029 break;
2030 case Hash("umullt_z_zzi_d"):
2031 VIXL_UNIMPLEMENTED();
2032 break;
2033 default:
2034 VIXL_UNIMPLEMENTED();
2035 }
2036}
2037
2038void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2039 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2040 USE(pg);
2041 SimVRegister& zd = ReadVRegister(instr->GetRd());
2042 USE(zd);
2043 SimVRegister& zn = ReadVRegister(instr->GetRn());
2044 USE(zn);
2045
2046 switch (form_hash_) {
2047 case Hash("fcvtnt_z_p_z_s2h"):
2048 VIXL_UNIMPLEMENTED();
2049 break;
2050 default:
2051 VIXL_UNIMPLEMENTED();
2052 }
2053}
2054
2055void Simulator::Simulate_ZdH_ZnH_ZmH_imm(const Instruction* instr) {
2056 SimVRegister& zd = ReadVRegister(instr->GetRd());
2057 USE(zd);
2058 SimVRegister& zn = ReadVRegister(instr->GetRn());
2059 USE(zn);
2060
2061 switch (form_hash_) {
2062 case Hash("mul_z_zzi_h"):
2063 VIXL_UNIMPLEMENTED();
2064 break;
2065 case Hash("sqdmulh_z_zzi_h"):
2066 VIXL_UNIMPLEMENTED();
2067 break;
2068 case Hash("sqrdmulh_z_zzi_h"):
2069 VIXL_UNIMPLEMENTED();
2070 break;
2071 default:
2072 VIXL_UNIMPLEMENTED();
2073 }
2074}
2075
2076void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2077 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2078 USE(pg);
2079 SimVRegister& zd = ReadVRegister(instr->GetRd());
2080 USE(zd);
2081 SimVRegister& zn = ReadVRegister(instr->GetRn());
2082 USE(zn);
2083
2084 switch (form_hash_) {
2085 case Hash("fcvtnt_z_p_z_d2s"):
2086 VIXL_UNIMPLEMENTED();
2087 break;
2088 case Hash("fcvtx_z_p_z_d2s"):
2089 VIXL_UNIMPLEMENTED();
2090 break;
2091 case Hash("fcvtxnt_z_p_z_d2s"):
2092 VIXL_UNIMPLEMENTED();
2093 break;
2094 default:
2095 VIXL_UNIMPLEMENTED();
2096 }
2097}
2098
2099void Simulator::Simulate_ZdS_PgM_ZnH(const Instruction* instr) {
2100 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2101 USE(pg);
2102 SimVRegister& zd = ReadVRegister(instr->GetRd());
2103 USE(zd);
2104 SimVRegister& zn = ReadVRegister(instr->GetRn());
2105 USE(zn);
2106
2107 switch (form_hash_) {
2108 case Hash("fcvtlt_z_p_z_h2s"):
2109 VIXL_UNIMPLEMENTED();
2110 break;
2111 default:
2112 VIXL_UNIMPLEMENTED();
2113 }
2114}
2115
2116void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
2117 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2118 USE(pg);
2119 SimVRegister& zd = ReadVRegister(instr->GetRd());
2120 USE(zd);
2121 SimVRegister& zn = ReadVRegister(instr->GetRn());
2122 USE(zn);
2123
2124 switch (form_hash_) {
2125 case Hash("urecpe_z_p_z"):
2126 VIXL_UNIMPLEMENTED();
2127 break;
2128 case Hash("ursqrte_z_p_z"):
2129 VIXL_UNIMPLEMENTED();
2130 break;
2131 default:
2132 VIXL_UNIMPLEMENTED();
2133 }
2134}
2135
2136void Simulator::Simulate_ZdS_ZnH_ZmH_imm(const Instruction* instr) {
2137 SimVRegister& zd = ReadVRegister(instr->GetRd());
2138 USE(zd);
2139 SimVRegister& zn = ReadVRegister(instr->GetRn());
2140 USE(zn);
2141
2142 switch (form_hash_) {
2143 case Hash("smullb_z_zzi_s"):
2144 VIXL_UNIMPLEMENTED();
2145 break;
2146 case Hash("smullt_z_zzi_s"):
2147 VIXL_UNIMPLEMENTED();
2148 break;
2149 case Hash("sqdmullb_z_zzi_s"):
2150 VIXL_UNIMPLEMENTED();
2151 break;
2152 case Hash("sqdmullt_z_zzi_s"):
2153 VIXL_UNIMPLEMENTED();
2154 break;
2155 case Hash("umullb_z_zzi_s"):
2156 VIXL_UNIMPLEMENTED();
2157 break;
2158 case Hash("umullt_z_zzi_s"):
2159 VIXL_UNIMPLEMENTED();
2160 break;
2161 default:
2162 VIXL_UNIMPLEMENTED();
2163 }
2164}
2165
2166void Simulator::Simulate_ZdS_ZnS_ZmS_imm(const Instruction* instr) {
2167 SimVRegister& zd = ReadVRegister(instr->GetRd());
2168 USE(zd);
2169 SimVRegister& zn = ReadVRegister(instr->GetRn());
2170 USE(zn);
2171
2172 switch (form_hash_) {
2173 case Hash("mul_z_zzi_s"):
2174 VIXL_UNIMPLEMENTED();
2175 break;
2176 case Hash("sqdmulh_z_zzi_s"):
2177 VIXL_UNIMPLEMENTED();
2178 break;
2179 case Hash("sqrdmulh_z_zzi_s"):
2180 VIXL_UNIMPLEMENTED();
2181 break;
2182 default:
2183 VIXL_UNIMPLEMENTED();
2184 }
2185}
2186
2187void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
2188 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2189 USE(pg);
2190 SimVRegister& zd = ReadVRegister(instr->GetRd());
2191 USE(zd);
2192 SimVRegister& zn = ReadVRegister(instr->GetRn());
2193 USE(zn);
2194
2195 switch (form_hash_) {
2196 case Hash("flogb_z_p_z"):
2197 VIXL_UNIMPLEMENTED();
2198 break;
2199 case Hash("sqabs_z_p_z"):
2200 VIXL_UNIMPLEMENTED();
2201 break;
2202 case Hash("sqneg_z_p_z"):
2203 VIXL_UNIMPLEMENTED();
2204 break;
2205 default:
2206 VIXL_UNIMPLEMENTED();
2207 }
2208}
2209
2210void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
2211 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2212 USE(pg);
2213 SimVRegister& zd = ReadVRegister(instr->GetRd());
2214 USE(zd);
2215 SimVRegister& zm = ReadVRegister(instr->GetRm());
2216 USE(zm);
2217 SimVRegister& zn = ReadVRegister(instr->GetRn());
2218 USE(zn);
2219
2220 switch (form_hash_) {
2221 case Hash("histcnt_z_p_zz"):
2222 VIXL_UNIMPLEMENTED();
2223 break;
2224 default:
2225 VIXL_UNIMPLEMENTED();
2226 }
2227}
2228
2229void Simulator::Simulate_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr) {
2230 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2231 USE(pg);
2232 SimVRegister& zd = ReadVRegister(instr->GetRd());
2233 USE(zd);
2234 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
2235 USE(zn1);
2236
2237 switch (form_hash_) {
2238 case Hash("splice_z_p_zz_con"):
2239 VIXL_UNIMPLEMENTED();
2240 break;
2241 default:
2242 VIXL_UNIMPLEMENTED();
2243 }
2244}
2245
2246void Simulator::Simulate_ZdT_Zn1T_Zn2T_ZmT(const Instruction* instr) {
2247 SimVRegister& zd = ReadVRegister(instr->GetRd());
2248 USE(zd);
2249 SimVRegister& zm = ReadVRegister(instr->GetRm());
2250 USE(zm);
2251 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
2252 USE(zn1);
2253
2254 switch (form_hash_) {
2255 case Hash("tbl_z_zz_2"):
2256 VIXL_UNIMPLEMENTED();
2257 break;
2258 default:
2259 VIXL_UNIMPLEMENTED();
2260 }
2261}
2262
2263void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
2264 SimVRegister& zd = ReadVRegister(instr->GetRd());
2265 USE(zd);
2266 SimVRegister& zm = ReadVRegister(instr->GetRm());
2267 USE(zm);
2268 SimVRegister& zn = ReadVRegister(instr->GetRn());
2269 USE(zn);
2270
2271 switch (form_hash_) {
2272 case Hash("bdep_z_zz"):
2273 VIXL_UNIMPLEMENTED();
2274 break;
2275 case Hash("bext_z_zz"):
2276 VIXL_UNIMPLEMENTED();
2277 break;
2278 case Hash("bgrp_z_zz"):
2279 VIXL_UNIMPLEMENTED();
2280 break;
2281 case Hash("eorbt_z_zz"):
2282 VIXL_UNIMPLEMENTED();
2283 break;
2284 case Hash("eortb_z_zz"):
2285 VIXL_UNIMPLEMENTED();
2286 break;
2287 case Hash("mul_z_zz"):
2288 VIXL_UNIMPLEMENTED();
2289 break;
2290 case Hash("smulh_z_zz"):
2291 VIXL_UNIMPLEMENTED();
2292 break;
2293 case Hash("sqdmulh_z_zz"):
2294 VIXL_UNIMPLEMENTED();
2295 break;
2296 case Hash("sqrdmulh_z_zz"):
2297 VIXL_UNIMPLEMENTED();
2298 break;
2299 case Hash("tbx_z_zz"):
2300 VIXL_UNIMPLEMENTED();
2301 break;
2302 case Hash("umulh_z_zz"):
2303 VIXL_UNIMPLEMENTED();
2304 break;
2305 default:
2306 VIXL_UNIMPLEMENTED();
2307 }
2308}
2309
2310void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
2311 SimVRegister& zd = ReadVRegister(instr->GetRd());
2312 USE(zd);
2313 SimVRegister& zm = ReadVRegister(instr->GetRm());
2314 USE(zm);
2315 SimVRegister& zn = ReadVRegister(instr->GetRn());
2316 USE(zn);
2317
2318 switch (form_hash_) {
2319 case Hash("saddwb_z_zz"):
2320 VIXL_UNIMPLEMENTED();
2321 break;
2322 case Hash("saddwt_z_zz"):
2323 VIXL_UNIMPLEMENTED();
2324 break;
2325 case Hash("ssubwb_z_zz"):
2326 VIXL_UNIMPLEMENTED();
2327 break;
2328 case Hash("ssubwt_z_zz"):
2329 VIXL_UNIMPLEMENTED();
2330 break;
2331 case Hash("uaddwb_z_zz"):
2332 VIXL_UNIMPLEMENTED();
2333 break;
2334 case Hash("uaddwt_z_zz"):
2335 VIXL_UNIMPLEMENTED();
2336 break;
2337 case Hash("usubwb_z_zz"):
2338 VIXL_UNIMPLEMENTED();
2339 break;
2340 case Hash("usubwt_z_zz"):
2341 VIXL_UNIMPLEMENTED();
2342 break;
2343 default:
2344 VIXL_UNIMPLEMENTED();
2345 }
2346}
2347
2348void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2349 SimVRegister& zd = ReadVRegister(instr->GetRd());
2350 USE(zd);
2351 SimVRegister& zn = ReadVRegister(instr->GetRn());
2352 USE(zn);
2353
2354 switch (form_hash_) {
2355 case Hash("sli_z_zzi"):
2356 VIXL_UNIMPLEMENTED();
2357 break;
2358 case Hash("sri_z_zzi"):
2359 VIXL_UNIMPLEMENTED();
2360 break;
2361 default:
2362 VIXL_UNIMPLEMENTED();
2363 }
2364}
2365
2366void Simulator::Simulate_ZdT_ZnTb(const Instruction* instr) {
2367 SimVRegister& zd = ReadVRegister(instr->GetRd());
2368 USE(zd);
2369 SimVRegister& zn = ReadVRegister(instr->GetRn());
2370 USE(zn);
2371
2372 switch (form_hash_) {
2373 case Hash("sqxtnb_z_zz"):
2374 VIXL_UNIMPLEMENTED();
2375 break;
2376 case Hash("sqxtnt_z_zz"):
2377 VIXL_UNIMPLEMENTED();
2378 break;
2379 case Hash("sqxtunb_z_zz"):
2380 VIXL_UNIMPLEMENTED();
2381 break;
2382 case Hash("sqxtunt_z_zz"):
2383 VIXL_UNIMPLEMENTED();
2384 break;
2385 case Hash("uqxtnb_z_zz"):
2386 VIXL_UNIMPLEMENTED();
2387 break;
2388 case Hash("uqxtnt_z_zz"):
2389 VIXL_UNIMPLEMENTED();
2390 break;
2391 default:
2392 VIXL_UNIMPLEMENTED();
2393 }
2394}
2395
2396void Simulator::Simulate_ZdT_ZnTb_ZmTb(const Instruction* instr) {
2397 SimVRegister& zd = ReadVRegister(instr->GetRd());
2398 USE(zd);
2399 SimVRegister& zm = ReadVRegister(instr->GetRm());
2400 USE(zm);
2401 SimVRegister& zn = ReadVRegister(instr->GetRn());
2402 USE(zn);
2403
2404 switch (form_hash_) {
2405 case Hash("addhnb_z_zz"):
2406 VIXL_UNIMPLEMENTED();
2407 break;
2408 case Hash("addhnt_z_zz"):
2409 VIXL_UNIMPLEMENTED();
2410 break;
2411 case Hash("pmullb_z_zz"):
2412 VIXL_UNIMPLEMENTED();
2413 break;
2414 case Hash("pmullt_z_zz"):
2415 VIXL_UNIMPLEMENTED();
2416 break;
2417 case Hash("raddhnb_z_zz"):
2418 VIXL_UNIMPLEMENTED();
2419 break;
2420 case Hash("raddhnt_z_zz"):
2421 VIXL_UNIMPLEMENTED();
2422 break;
2423 case Hash("rsubhnb_z_zz"):
2424 VIXL_UNIMPLEMENTED();
2425 break;
2426 case Hash("rsubhnt_z_zz"):
2427 VIXL_UNIMPLEMENTED();
2428 break;
2429 case Hash("sabdlb_z_zz"):
2430 VIXL_UNIMPLEMENTED();
2431 break;
2432 case Hash("sabdlt_z_zz"):
2433 VIXL_UNIMPLEMENTED();
2434 break;
2435 case Hash("saddlb_z_zz"):
2436 VIXL_UNIMPLEMENTED();
2437 break;
2438 case Hash("saddlbt_z_zz"):
2439 VIXL_UNIMPLEMENTED();
2440 break;
2441 case Hash("saddlt_z_zz"):
2442 VIXL_UNIMPLEMENTED();
2443 break;
2444 case Hash("smullb_z_zz"):
2445 VIXL_UNIMPLEMENTED();
2446 break;
2447 case Hash("smullt_z_zz"):
2448 VIXL_UNIMPLEMENTED();
2449 break;
2450 case Hash("sqdmullb_z_zz"):
2451 VIXL_UNIMPLEMENTED();
2452 break;
2453 case Hash("sqdmullt_z_zz"):
2454 VIXL_UNIMPLEMENTED();
2455 break;
2456 case Hash("ssublb_z_zz"):
2457 VIXL_UNIMPLEMENTED();
2458 break;
2459 case Hash("ssublbt_z_zz"):
2460 VIXL_UNIMPLEMENTED();
2461 break;
2462 case Hash("ssublt_z_zz"):
2463 VIXL_UNIMPLEMENTED();
2464 break;
2465 case Hash("ssubltb_z_zz"):
2466 VIXL_UNIMPLEMENTED();
2467 break;
2468 case Hash("subhnb_z_zz"):
2469 VIXL_UNIMPLEMENTED();
2470 break;
2471 case Hash("subhnt_z_zz"):
2472 VIXL_UNIMPLEMENTED();
2473 break;
2474 case Hash("uabdlb_z_zz"):
2475 VIXL_UNIMPLEMENTED();
2476 break;
2477 case Hash("uabdlt_z_zz"):
2478 VIXL_UNIMPLEMENTED();
2479 break;
2480 case Hash("uaddlb_z_zz"):
2481 VIXL_UNIMPLEMENTED();
2482 break;
2483 case Hash("uaddlt_z_zz"):
2484 VIXL_UNIMPLEMENTED();
2485 break;
2486 case Hash("umullb_z_zz"):
2487 VIXL_UNIMPLEMENTED();
2488 break;
2489 case Hash("umullt_z_zz"):
2490 VIXL_UNIMPLEMENTED();
2491 break;
2492 case Hash("usublb_z_zz"):
2493 VIXL_UNIMPLEMENTED();
2494 break;
2495 case Hash("usublt_z_zz"):
2496 VIXL_UNIMPLEMENTED();
2497 break;
2498 default:
2499 VIXL_UNIMPLEMENTED();
2500 }
2501}
2502
2503void Simulator::Simulate_ZdT_ZnTb_const(const Instruction* instr) {
2504 SimVRegister& zd = ReadVRegister(instr->GetRd());
2505 USE(zd);
2506 SimVRegister& zn = ReadVRegister(instr->GetRn());
2507 USE(zn);
2508
2509 switch (form_hash_) {
2510 case Hash("rshrnb_z_zi"):
2511 VIXL_UNIMPLEMENTED();
2512 break;
2513 case Hash("rshrnt_z_zi"):
2514 VIXL_UNIMPLEMENTED();
2515 break;
2516 case Hash("shrnb_z_zi"):
2517 VIXL_UNIMPLEMENTED();
2518 break;
2519 case Hash("shrnt_z_zi"):
2520 VIXL_UNIMPLEMENTED();
2521 break;
2522 case Hash("sqrshrnb_z_zi"):
2523 VIXL_UNIMPLEMENTED();
2524 break;
2525 case Hash("sqrshrnt_z_zi"):
2526 VIXL_UNIMPLEMENTED();
2527 break;
2528 case Hash("sqrshrunb_z_zi"):
2529 VIXL_UNIMPLEMENTED();
2530 break;
2531 case Hash("sqrshrunt_z_zi"):
2532 VIXL_UNIMPLEMENTED();
2533 break;
2534 case Hash("sqshrnb_z_zi"):
2535 VIXL_UNIMPLEMENTED();
2536 break;
2537 case Hash("sqshrnt_z_zi"):
2538 VIXL_UNIMPLEMENTED();
2539 break;
2540 case Hash("sqshrunb_z_zi"):
2541 VIXL_UNIMPLEMENTED();
2542 break;
2543 case Hash("sqshrunt_z_zi"):
2544 VIXL_UNIMPLEMENTED();
2545 break;
2546 case Hash("sshllb_z_zi"):
2547 VIXL_UNIMPLEMENTED();
2548 break;
2549 case Hash("sshllt_z_zi"):
2550 VIXL_UNIMPLEMENTED();
2551 break;
2552 case Hash("uqrshrnb_z_zi"):
2553 VIXL_UNIMPLEMENTED();
2554 break;
2555 case Hash("uqrshrnt_z_zi"):
2556 VIXL_UNIMPLEMENTED();
2557 break;
2558 case Hash("uqshrnb_z_zi"):
2559 VIXL_UNIMPLEMENTED();
2560 break;
2561 case Hash("uqshrnt_z_zi"):
2562 VIXL_UNIMPLEMENTED();
2563 break;
2564 case Hash("ushllb_z_zi"):
2565 VIXL_UNIMPLEMENTED();
2566 break;
2567 case Hash("ushllt_z_zi"):
2568 VIXL_UNIMPLEMENTED();
2569 break;
2570 default:
2571 VIXL_UNIMPLEMENTED();
2572 }
2573}
2574
2575void Simulator::Simulate_ZdaD_ZnD_ZmD_imm(const Instruction* instr) {
2576 SimVRegister& zda = ReadVRegister(instr->GetRd());
2577 USE(zda);
2578 SimVRegister& zn = ReadVRegister(instr->GetRn());
2579 USE(zn);
2580
2581 switch (form_hash_) {
2582 case Hash("mla_z_zzzi_d"):
2583 VIXL_UNIMPLEMENTED();
2584 break;
2585 case Hash("mls_z_zzzi_d"):
2586 VIXL_UNIMPLEMENTED();
2587 break;
2588 case Hash("sqrdmlah_z_zzzi_d"):
2589 VIXL_UNIMPLEMENTED();
2590 break;
2591 case Hash("sqrdmlsh_z_zzzi_d"):
2592 VIXL_UNIMPLEMENTED();
2593 break;
2594 default:
2595 VIXL_UNIMPLEMENTED();
2596 }
2597}
2598
2599void Simulator::Simulate_ZdaD_ZnH_ZmH_imm_const(const Instruction* instr) {
2600 SimVRegister& zda = ReadVRegister(instr->GetRd());
2601 USE(zda);
2602 SimVRegister& zn = ReadVRegister(instr->GetRn());
2603 USE(zn);
2604
2605 switch (form_hash_) {
2606 case Hash("cdot_z_zzzi_d"):
2607 VIXL_UNIMPLEMENTED();
2608 break;
2609 default:
2610 VIXL_UNIMPLEMENTED();
2611 }
2612}
2613
2614void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2615 SimVRegister& zda = ReadVRegister(instr->GetRd());
2616 USE(zda);
2617 SimVRegister& zn = ReadVRegister(instr->GetRn());
2618 USE(zn);
2619
2620 switch (form_hash_) {
2621 case Hash("smlalb_z_zzzi_d"):
2622 VIXL_UNIMPLEMENTED();
2623 break;
2624 case Hash("smlalt_z_zzzi_d"):
2625 VIXL_UNIMPLEMENTED();
2626 break;
2627 case Hash("smlslb_z_zzzi_d"):
2628 VIXL_UNIMPLEMENTED();
2629 break;
2630 case Hash("smlslt_z_zzzi_d"):
2631 VIXL_UNIMPLEMENTED();
2632 break;
2633 case Hash("sqdmlalb_z_zzzi_d"):
2634 VIXL_UNIMPLEMENTED();
2635 break;
2636 case Hash("sqdmlalt_z_zzzi_d"):
2637 VIXL_UNIMPLEMENTED();
2638 break;
2639 case Hash("sqdmlslb_z_zzzi_d"):
2640 VIXL_UNIMPLEMENTED();
2641 break;
2642 case Hash("sqdmlslt_z_zzzi_d"):
2643 VIXL_UNIMPLEMENTED();
2644 break;
2645 case Hash("umlalb_z_zzzi_d"):
2646 VIXL_UNIMPLEMENTED();
2647 break;
2648 case Hash("umlalt_z_zzzi_d"):
2649 VIXL_UNIMPLEMENTED();
2650 break;
2651 case Hash("umlslb_z_zzzi_d"):
2652 VIXL_UNIMPLEMENTED();
2653 break;
2654 case Hash("umlslt_z_zzzi_d"):
2655 VIXL_UNIMPLEMENTED();
2656 break;
2657 default:
2658 VIXL_UNIMPLEMENTED();
2659 }
2660}
2661
2662void Simulator::Simulate_ZdaH_ZnH_ZmH_imm(const Instruction* instr) {
2663 SimVRegister& zda = ReadVRegister(instr->GetRd());
2664 USE(zda);
2665 SimVRegister& zn = ReadVRegister(instr->GetRn());
2666 USE(zn);
2667
2668 switch (form_hash_) {
2669 case Hash("mla_z_zzzi_h"):
2670 VIXL_UNIMPLEMENTED();
2671 break;
2672 case Hash("mls_z_zzzi_h"):
2673 VIXL_UNIMPLEMENTED();
2674 break;
2675 case Hash("sqrdmlah_z_zzzi_h"):
2676 VIXL_UNIMPLEMENTED();
2677 break;
2678 case Hash("sqrdmlsh_z_zzzi_h"):
2679 VIXL_UNIMPLEMENTED();
2680 break;
2681 default:
2682 VIXL_UNIMPLEMENTED();
2683 }
2684}
2685
2686void Simulator::Simulate_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr) {
2687 SimVRegister& zda = ReadVRegister(instr->GetRd());
2688 USE(zda);
2689 SimVRegister& zn = ReadVRegister(instr->GetRn());
2690 USE(zn);
2691
2692 switch (form_hash_) {
2693 case Hash("cmla_z_zzzi_h"):
2694 VIXL_UNIMPLEMENTED();
2695 break;
2696 case Hash("sqrdcmlah_z_zzzi_h"):
2697 VIXL_UNIMPLEMENTED();
2698 break;
2699 default:
2700 VIXL_UNIMPLEMENTED();
2701 }
2702}
2703
2704void Simulator::Simulate_ZdaS_ZnB_ZmB_imm_const(const Instruction* instr) {
2705 SimVRegister& zda = ReadVRegister(instr->GetRd());
2706 USE(zda);
2707 SimVRegister& zn = ReadVRegister(instr->GetRn());
2708 USE(zn);
2709
2710 switch (form_hash_) {
2711 case Hash("cdot_z_zzzi_s"):
2712 VIXL_UNIMPLEMENTED();
2713 break;
2714 default:
2715 VIXL_UNIMPLEMENTED();
2716 }
2717}
2718
2719void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2720 SimVRegister& zda = ReadVRegister(instr->GetRd());
2721 USE(zda);
2722 SimVRegister& zm = ReadVRegister(instr->GetRm());
2723 USE(zm);
2724 SimVRegister& zn = ReadVRegister(instr->GetRn());
2725 USE(zn);
2726
2727 switch (form_hash_) {
2728 case Hash("fmlalb_z_zzz"):
2729 VIXL_UNIMPLEMENTED();
2730 break;
2731 case Hash("fmlalt_z_zzz"):
2732 VIXL_UNIMPLEMENTED();
2733 break;
2734 case Hash("fmlslb_z_zzz"):
2735 VIXL_UNIMPLEMENTED();
2736 break;
2737 case Hash("fmlslt_z_zzz"):
2738 VIXL_UNIMPLEMENTED();
2739 break;
2740 default:
2741 VIXL_UNIMPLEMENTED();
2742 }
2743}
2744
2745void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2746 SimVRegister& zda = ReadVRegister(instr->GetRd());
2747 USE(zda);
2748 SimVRegister& zm = ReadVRegister(instr->GetRm());
2749 USE(zm);
2750 SimVRegister& zn = ReadVRegister(instr->GetRn());
2751 USE(zn);
2752
2753 switch (form_hash_) {
2754 case Hash("fmlalb_z_zzzi_s"):
2755 VIXL_UNIMPLEMENTED();
2756 break;
2757 case Hash("fmlalt_z_zzzi_s"):
2758 VIXL_UNIMPLEMENTED();
2759 break;
2760 case Hash("fmlslb_z_zzzi_s"):
2761 VIXL_UNIMPLEMENTED();
2762 break;
2763 case Hash("fmlslt_z_zzzi_s"):
2764 VIXL_UNIMPLEMENTED();
2765 break;
2766 case Hash("smlalb_z_zzzi_s"):
2767 VIXL_UNIMPLEMENTED();
2768 break;
2769 case Hash("smlalt_z_zzzi_s"):
2770 VIXL_UNIMPLEMENTED();
2771 break;
2772 case Hash("smlslb_z_zzzi_s"):
2773 VIXL_UNIMPLEMENTED();
2774 break;
2775 case Hash("smlslt_z_zzzi_s"):
2776 VIXL_UNIMPLEMENTED();
2777 break;
2778 case Hash("sqdmlalb_z_zzzi_s"):
2779 VIXL_UNIMPLEMENTED();
2780 break;
2781 case Hash("sqdmlalt_z_zzzi_s"):
2782 VIXL_UNIMPLEMENTED();
2783 break;
2784 case Hash("sqdmlslb_z_zzzi_s"):
2785 VIXL_UNIMPLEMENTED();
2786 break;
2787 case Hash("sqdmlslt_z_zzzi_s"):
2788 VIXL_UNIMPLEMENTED();
2789 break;
2790 case Hash("umlalb_z_zzzi_s"):
2791 VIXL_UNIMPLEMENTED();
2792 break;
2793 case Hash("umlalt_z_zzzi_s"):
2794 VIXL_UNIMPLEMENTED();
2795 break;
2796 case Hash("umlslb_z_zzzi_s"):
2797 VIXL_UNIMPLEMENTED();
2798 break;
2799 case Hash("umlslt_z_zzzi_s"):
2800 VIXL_UNIMPLEMENTED();
2801 break;
2802 default:
2803 VIXL_UNIMPLEMENTED();
2804 }
2805}
2806
2807void Simulator::Simulate_ZdaS_ZnS_ZmS_imm(const Instruction* instr) {
2808 SimVRegister& zda = ReadVRegister(instr->GetRd());
2809 USE(zda);
2810 SimVRegister& zn = ReadVRegister(instr->GetRn());
2811 USE(zn);
2812
2813 switch (form_hash_) {
2814 case Hash("mla_z_zzzi_s"):
2815 VIXL_UNIMPLEMENTED();
2816 break;
2817 case Hash("mls_z_zzzi_s"):
2818 VIXL_UNIMPLEMENTED();
2819 break;
2820 case Hash("sqrdmlah_z_zzzi_s"):
2821 VIXL_UNIMPLEMENTED();
2822 break;
2823 case Hash("sqrdmlsh_z_zzzi_s"):
2824 VIXL_UNIMPLEMENTED();
2825 break;
2826 default:
2827 VIXL_UNIMPLEMENTED();
2828 }
2829}
2830
2831void Simulator::Simulate_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr) {
2832 SimVRegister& zda = ReadVRegister(instr->GetRd());
2833 USE(zda);
2834 SimVRegister& zn = ReadVRegister(instr->GetRn());
2835 USE(zn);
2836
2837 switch (form_hash_) {
2838 case Hash("cmla_z_zzzi_s"):
2839 VIXL_UNIMPLEMENTED();
2840 break;
2841 case Hash("sqrdcmlah_z_zzzi_s"):
2842 VIXL_UNIMPLEMENTED();
2843 break;
2844 default:
2845 VIXL_UNIMPLEMENTED();
2846 }
2847}
2848
2849void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
2850 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2851 USE(pg);
2852 SimVRegister& zda = ReadVRegister(instr->GetRd());
2853 USE(zda);
2854 SimVRegister& zn = ReadVRegister(instr->GetRn());
2855 USE(zn);
2856
2857 switch (form_hash_) {
2858 case Hash("sadalp_z_p_z"):
2859 VIXL_UNIMPLEMENTED();
2860 break;
2861 case Hash("uadalp_z_p_z"):
2862 VIXL_UNIMPLEMENTED();
2863 break;
2864 default:
2865 VIXL_UNIMPLEMENTED();
2866 }
2867}
2868
2869void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
2870 SimVRegister& zda = ReadVRegister(instr->GetRd());
2871 USE(zda);
2872 SimVRegister& zm = ReadVRegister(instr->GetRm());
2873 USE(zm);
2874 SimVRegister& zn = ReadVRegister(instr->GetRn());
2875 USE(zn);
2876
2877 switch (form_hash_) {
2878 case Hash("adclb_z_zzz"):
2879 VIXL_UNIMPLEMENTED();
2880 break;
2881 case Hash("adclt_z_zzz"):
2882 VIXL_UNIMPLEMENTED();
2883 break;
2884 case Hash("saba_z_zzz"):
2885 VIXL_UNIMPLEMENTED();
2886 break;
2887 case Hash("sbclb_z_zzz"):
2888 VIXL_UNIMPLEMENTED();
2889 break;
2890 case Hash("sbclt_z_zzz"):
2891 VIXL_UNIMPLEMENTED();
2892 break;
2893 case Hash("sqrdmlah_z_zzz"):
2894 VIXL_UNIMPLEMENTED();
2895 break;
2896 case Hash("sqrdmlsh_z_zzz"):
2897 VIXL_UNIMPLEMENTED();
2898 break;
2899 case Hash("uaba_z_zzz"):
2900 VIXL_UNIMPLEMENTED();
2901 break;
2902 default:
2903 VIXL_UNIMPLEMENTED();
2904 }
2905}
2906
2907void Simulator::Simulate_ZdaT_ZnT_ZmT_const(const Instruction* instr) {
2908 SimVRegister& zda = ReadVRegister(instr->GetRd());
2909 USE(zda);
2910 SimVRegister& zm = ReadVRegister(instr->GetRm());
2911 USE(zm);
2912 SimVRegister& zn = ReadVRegister(instr->GetRn());
2913 USE(zn);
2914
2915 switch (form_hash_) {
2916 case Hash("cmla_z_zzz"):
2917 VIXL_UNIMPLEMENTED();
2918 break;
2919 case Hash("sqrdcmlah_z_zzz"):
2920 VIXL_UNIMPLEMENTED();
2921 break;
2922 default:
2923 VIXL_UNIMPLEMENTED();
2924 }
2925}
2926
2927void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
2928 SimVRegister& zda = ReadVRegister(instr->GetRd());
2929 USE(zda);
2930 SimVRegister& zn = ReadVRegister(instr->GetRn());
2931 USE(zn);
2932
2933 switch (form_hash_) {
2934 case Hash("srsra_z_zi"):
2935 VIXL_UNIMPLEMENTED();
2936 break;
2937 case Hash("ssra_z_zi"):
2938 VIXL_UNIMPLEMENTED();
2939 break;
2940 case Hash("ursra_z_zi"):
2941 VIXL_UNIMPLEMENTED();
2942 break;
2943 case Hash("usra_z_zi"):
2944 VIXL_UNIMPLEMENTED();
2945 break;
2946 default:
2947 VIXL_UNIMPLEMENTED();
2948 }
2949}
2950
2951void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
2952 SimVRegister& zda = ReadVRegister(instr->GetRd());
2953 USE(zda);
2954 SimVRegister& zm = ReadVRegister(instr->GetRm());
2955 USE(zm);
2956 SimVRegister& zn = ReadVRegister(instr->GetRn());
2957 USE(zn);
2958
2959 switch (form_hash_) {
2960 case Hash("sabalb_z_zzz"):
2961 VIXL_UNIMPLEMENTED();
2962 break;
2963 case Hash("sabalt_z_zzz"):
2964 VIXL_UNIMPLEMENTED();
2965 break;
2966 case Hash("smlalb_z_zzz"):
2967 VIXL_UNIMPLEMENTED();
2968 break;
2969 case Hash("smlalt_z_zzz"):
2970 VIXL_UNIMPLEMENTED();
2971 break;
2972 case Hash("smlslb_z_zzz"):
2973 VIXL_UNIMPLEMENTED();
2974 break;
2975 case Hash("smlslt_z_zzz"):
2976 VIXL_UNIMPLEMENTED();
2977 break;
2978 case Hash("sqdmlalb_z_zzz"):
2979 VIXL_UNIMPLEMENTED();
2980 break;
2981 case Hash("sqdmlalbt_z_zzz"):
2982 VIXL_UNIMPLEMENTED();
2983 break;
2984 case Hash("sqdmlalt_z_zzz"):
2985 VIXL_UNIMPLEMENTED();
2986 break;
2987 case Hash("sqdmlslb_z_zzz"):
2988 VIXL_UNIMPLEMENTED();
2989 break;
2990 case Hash("sqdmlslbt_z_zzz"):
2991 VIXL_UNIMPLEMENTED();
2992 break;
2993 case Hash("sqdmlslt_z_zzz"):
2994 VIXL_UNIMPLEMENTED();
2995 break;
2996 case Hash("uabalb_z_zzz"):
2997 VIXL_UNIMPLEMENTED();
2998 break;
2999 case Hash("uabalt_z_zzz"):
3000 VIXL_UNIMPLEMENTED();
3001 break;
3002 case Hash("umlalb_z_zzz"):
3003 VIXL_UNIMPLEMENTED();
3004 break;
3005 case Hash("umlalt_z_zzz"):
3006 VIXL_UNIMPLEMENTED();
3007 break;
3008 case Hash("umlslb_z_zzz"):
3009 VIXL_UNIMPLEMENTED();
3010 break;
3011 case Hash("umlslt_z_zzz"):
3012 VIXL_UNIMPLEMENTED();
3013 break;
3014 default:
3015 VIXL_UNIMPLEMENTED();
3016 }
3017}
3018
3019void Simulator::Simulate_ZdaT_ZnTb_ZmTb_const(const Instruction* instr) {
3020 SimVRegister& zda = ReadVRegister(instr->GetRd());
3021 USE(zda);
3022 SimVRegister& zm = ReadVRegister(instr->GetRm());
3023 USE(zm);
3024 SimVRegister& zn = ReadVRegister(instr->GetRn());
3025 USE(zn);
3026
3027 switch (form_hash_) {
3028 case Hash("cdot_z_zzz"):
3029 VIXL_UNIMPLEMENTED();
3030 break;
3031 default:
3032 VIXL_UNIMPLEMENTED();
3033 }
3034}
3035
3036void Simulator::Simulate_ZdnD_ZdnD_ZmD_ZkD(const Instruction* instr) {
3037 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3038 USE(zdn);
3039 SimVRegister& zm = ReadVRegister(instr->GetRm());
3040 USE(zm);
3041
3042 switch (form_hash_) {
3043 case Hash("bcax_z_zzz"):
3044 VIXL_UNIMPLEMENTED();
3045 break;
3046 case Hash("bsl1n_z_zzz"):
3047 VIXL_UNIMPLEMENTED();
3048 break;
3049 case Hash("bsl2n_z_zzz"):
3050 VIXL_UNIMPLEMENTED();
3051 break;
3052 case Hash("bsl_z_zzz"):
3053 VIXL_UNIMPLEMENTED();
3054 break;
3055 case Hash("eor3_z_zzz"):
3056 VIXL_UNIMPLEMENTED();
3057 break;
3058 case Hash("nbsl_z_zzz"):
3059 VIXL_UNIMPLEMENTED();
3060 break;
3061 default:
3062 VIXL_UNIMPLEMENTED();
3063 }
3064}
3065
3066void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3067 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3068 USE(pg);
3069 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3070 USE(zdn);
3071 SimVRegister& zm = ReadVRegister(instr->GetRn());
3072 USE(zm);
3073
3074 switch (form_hash_) {
3075 case Hash("addp_z_p_zz"):
3076 VIXL_UNIMPLEMENTED();
3077 break;
3078 case Hash("faddp_z_p_zz"):
3079 VIXL_UNIMPLEMENTED();
3080 break;
3081 case Hash("fmaxnmp_z_p_zz"):
3082 VIXL_UNIMPLEMENTED();
3083 break;
3084 case Hash("fmaxp_z_p_zz"):
3085 VIXL_UNIMPLEMENTED();
3086 break;
3087 case Hash("fminnmp_z_p_zz"):
3088 VIXL_UNIMPLEMENTED();
3089 break;
3090 case Hash("fminp_z_p_zz"):
3091 VIXL_UNIMPLEMENTED();
3092 break;
3093 case Hash("shadd_z_p_zz"):
3094 VIXL_UNIMPLEMENTED();
3095 break;
3096 case Hash("shsub_z_p_zz"):
3097 VIXL_UNIMPLEMENTED();
3098 break;
3099 case Hash("shsubr_z_p_zz"):
3100 VIXL_UNIMPLEMENTED();
3101 break;
3102 case Hash("smaxp_z_p_zz"):
3103 VIXL_UNIMPLEMENTED();
3104 break;
3105 case Hash("sminp_z_p_zz"):
3106 VIXL_UNIMPLEMENTED();
3107 break;
3108 case Hash("sqadd_z_p_zz"):
3109 VIXL_UNIMPLEMENTED();
3110 break;
3111 case Hash("sqrshl_z_p_zz"):
3112 VIXL_UNIMPLEMENTED();
3113 break;
3114 case Hash("sqrshlr_z_p_zz"):
3115 VIXL_UNIMPLEMENTED();
3116 break;
3117 case Hash("sqshl_z_p_zz"):
3118 VIXL_UNIMPLEMENTED();
3119 break;
3120 case Hash("sqshlr_z_p_zz"):
3121 VIXL_UNIMPLEMENTED();
3122 break;
3123 case Hash("sqsub_z_p_zz"):
3124 VIXL_UNIMPLEMENTED();
3125 break;
3126 case Hash("sqsubr_z_p_zz"):
3127 VIXL_UNIMPLEMENTED();
3128 break;
3129 case Hash("srhadd_z_p_zz"):
3130 VIXL_UNIMPLEMENTED();
3131 break;
3132 case Hash("srshl_z_p_zz"):
3133 VIXL_UNIMPLEMENTED();
3134 break;
3135 case Hash("srshlr_z_p_zz"):
3136 VIXL_UNIMPLEMENTED();
3137 break;
3138 case Hash("suqadd_z_p_zz"):
3139 VIXL_UNIMPLEMENTED();
3140 break;
3141 case Hash("uhadd_z_p_zz"):
3142 VIXL_UNIMPLEMENTED();
3143 break;
3144 case Hash("uhsub_z_p_zz"):
3145 VIXL_UNIMPLEMENTED();
3146 break;
3147 case Hash("uhsubr_z_p_zz"):
3148 VIXL_UNIMPLEMENTED();
3149 break;
3150 case Hash("umaxp_z_p_zz"):
3151 VIXL_UNIMPLEMENTED();
3152 break;
3153 case Hash("uminp_z_p_zz"):
3154 VIXL_UNIMPLEMENTED();
3155 break;
3156 case Hash("uqadd_z_p_zz"):
3157 VIXL_UNIMPLEMENTED();
3158 break;
3159 case Hash("uqrshl_z_p_zz"):
3160 VIXL_UNIMPLEMENTED();
3161 break;
3162 case Hash("uqrshlr_z_p_zz"):
3163 VIXL_UNIMPLEMENTED();
3164 break;
3165 case Hash("uqshl_z_p_zz"):
3166 VIXL_UNIMPLEMENTED();
3167 break;
3168 case Hash("uqshlr_z_p_zz"):
3169 VIXL_UNIMPLEMENTED();
3170 break;
3171 case Hash("uqsub_z_p_zz"):
3172 VIXL_UNIMPLEMENTED();
3173 break;
3174 case Hash("uqsubr_z_p_zz"):
3175 VIXL_UNIMPLEMENTED();
3176 break;
3177 case Hash("urhadd_z_p_zz"):
3178 VIXL_UNIMPLEMENTED();
3179 break;
3180 case Hash("urshl_z_p_zz"):
3181 VIXL_UNIMPLEMENTED();
3182 break;
3183 case Hash("urshlr_z_p_zz"):
3184 VIXL_UNIMPLEMENTED();
3185 break;
3186 case Hash("usqadd_z_p_zz"):
3187 VIXL_UNIMPLEMENTED();
3188 break;
3189 default:
3190 VIXL_UNIMPLEMENTED();
3191 }
3192}
3193
3194void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3195 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3196 USE(pg);
3197 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3198 USE(zdn);
3199
3200 switch (form_hash_) {
3201 case Hash("sqshl_z_p_zi"):
3202 VIXL_UNIMPLEMENTED();
3203 break;
3204 case Hash("sqshlu_z_p_zi"):
3205 VIXL_UNIMPLEMENTED();
3206 break;
3207 case Hash("srshr_z_p_zi"):
3208 VIXL_UNIMPLEMENTED();
3209 break;
3210 case Hash("uqshl_z_p_zi"):
3211 VIXL_UNIMPLEMENTED();
3212 break;
3213 case Hash("urshr_z_p_zi"):
3214 VIXL_UNIMPLEMENTED();
3215 break;
3216 default:
3217 VIXL_UNIMPLEMENTED();
3218 }
3219}
3220
3221void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
3222 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3223 USE(zdn);
3224 SimVRegister& zm = ReadVRegister(instr->GetRn());
3225 USE(zm);
3226
3227 switch (form_hash_) {
3228 case Hash("cadd_z_zz"):
3229 VIXL_UNIMPLEMENTED();
3230 break;
3231 case Hash("sqcadd_z_zz"):
3232 VIXL_UNIMPLEMENTED();
3233 break;
3234 case Hash("xar_z_zzi"):
3235 VIXL_UNIMPLEMENTED();
3236 break;
3237 default:
3238 VIXL_UNIMPLEMENTED();
3239 }
3240}
3241
3242void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3243 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3244 USE(pg);
3245 SimVRegister& zn = ReadVRegister(instr->GetRn());
3246 USE(zn);
3247 SimVRegister& zt = ReadVRegister(instr->GetRt());
3248 USE(zt);
3249
3250 switch (form_hash_) {
3251 case Hash("ldnt1b_z_p_ar_d_64_unscaled"):
3252 VIXL_UNIMPLEMENTED();
3253 break;
3254 case Hash("ldnt1d_z_p_ar_d_64_unscaled"):
3255 VIXL_UNIMPLEMENTED();
3256 break;
3257 case Hash("ldnt1h_z_p_ar_d_64_unscaled"):
3258 VIXL_UNIMPLEMENTED();
3259 break;
3260 case Hash("ldnt1sb_z_p_ar_d_64_unscaled"):
3261 VIXL_UNIMPLEMENTED();
3262 break;
3263 case Hash("ldnt1sh_z_p_ar_d_64_unscaled"):
3264 VIXL_UNIMPLEMENTED();
3265 break;
3266 case Hash("ldnt1sw_z_p_ar_d_64_unscaled"):
3267 VIXL_UNIMPLEMENTED();
3268 break;
3269 case Hash("ldnt1w_z_p_ar_d_64_unscaled"):
3270 VIXL_UNIMPLEMENTED();
3271 break;
3272 default:
3273 VIXL_UNIMPLEMENTED();
3274 }
3275}
3276
3277void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3278 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3279 USE(pg);
3280 SimVRegister& zn = ReadVRegister(instr->GetRn());
3281 USE(zn);
3282 SimVRegister& zt = ReadVRegister(instr->GetRt());
3283 USE(zt);
3284
3285 switch (form_hash_) {
3286 case Hash("stnt1b_z_p_ar_d_64_unscaled"):
3287 VIXL_UNIMPLEMENTED();
3288 break;
3289 case Hash("stnt1d_z_p_ar_d_64_unscaled"):
3290 VIXL_UNIMPLEMENTED();
3291 break;
3292 case Hash("stnt1h_z_p_ar_d_64_unscaled"):
3293 VIXL_UNIMPLEMENTED();
3294 break;
3295 case Hash("stnt1w_z_p_ar_d_64_unscaled"):
3296 VIXL_UNIMPLEMENTED();
3297 break;
3298 default:
3299 VIXL_UNIMPLEMENTED();
3300 }
3301}
3302
3303void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3304 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3305 USE(pg);
3306 SimVRegister& zn = ReadVRegister(instr->GetRn());
3307 USE(zn);
3308 SimVRegister& zt = ReadVRegister(instr->GetRt());
3309 USE(zt);
3310
3311 switch (form_hash_) {
3312 case Hash("ldnt1b_z_p_ar_s_x32_unscaled"):
3313 VIXL_UNIMPLEMENTED();
3314 break;
3315 case Hash("ldnt1h_z_p_ar_s_x32_unscaled"):
3316 VIXL_UNIMPLEMENTED();
3317 break;
3318 case Hash("ldnt1sb_z_p_ar_s_x32_unscaled"):
3319 VIXL_UNIMPLEMENTED();
3320 break;
3321 case Hash("ldnt1sh_z_p_ar_s_x32_unscaled"):
3322 VIXL_UNIMPLEMENTED();
3323 break;
3324 case Hash("ldnt1w_z_p_ar_s_x32_unscaled"):
3325 VIXL_UNIMPLEMENTED();
3326 break;
3327 default:
3328 VIXL_UNIMPLEMENTED();
3329 }
3330}
3331
3332void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3333 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3334 USE(pg);
3335 SimVRegister& zn = ReadVRegister(instr->GetRn());
3336 USE(zn);
3337 SimVRegister& zt = ReadVRegister(instr->GetRt());
3338 USE(zt);
3339
3340 switch (form_hash_) {
3341 case Hash("stnt1b_z_p_ar_s_x32_unscaled"):
3342 VIXL_UNIMPLEMENTED();
3343 break;
3344 case Hash("stnt1h_z_p_ar_s_x32_unscaled"):
3345 VIXL_UNIMPLEMENTED();
3346 break;
3347 case Hash("stnt1w_z_p_ar_s_x32_unscaled"):
3348 VIXL_UNIMPLEMENTED();
3349 break;
3350 default:
3351 VIXL_UNIMPLEMENTED();
3352 }
3353}
3354
Jacob Bramley18c97bd2019-01-18 16:01:08 +00003355void Simulator::VisitReserved(const Instruction* instr) {
3356 // UDF is the only instruction in this group, and the Decoder is precise here.
3357 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3358
3359 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3360 reinterpret_cast<const void*>(instr),
3361 instr->GetInstructionBits());
3362 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3363}
3364
3365
Alexandre Ramesd3832962016-07-04 15:03:43 +01003366void Simulator::VisitUnimplemented(const Instruction* instr) {
3367 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3368 reinterpret_cast<const void*>(instr),
3369 instr->GetInstructionBits());
3370 VIXL_UNIMPLEMENTED();
3371}
3372
3373
3374void Simulator::VisitUnallocated(const Instruction* instr) {
3375 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3376 reinterpret_cast<const void*>(instr),
3377 instr->GetInstructionBits());
3378 VIXL_UNIMPLEMENTED();
3379}
3380
3381
3382void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3383 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3384 (instr->Mask(PCRelAddressingMask) == ADRP));
3385
3386 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3387}
3388
3389
3390void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3391 switch (instr->Mask(UnconditionalBranchMask)) {
3392 case BL:
3393 WriteLr(instr->GetNextInstruction());
3394 VIXL_FALLTHROUGH();
3395 case B:
3396 WritePc(instr->GetImmPCOffsetTarget());
3397 break;
3398 default:
3399 VIXL_UNREACHABLE();
3400 }
3401}
3402
3403
3404void Simulator::VisitConditionalBranch(const Instruction* instr) {
3405 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3406 if (ConditionPassed(instr->GetConditionBranch())) {
3407 WritePc(instr->GetImmPCOffsetTarget());
3408 }
3409}
3410
Martyn Capewellcb963f72018-10-22 15:25:28 +01003411BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3412 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3413 case BLR:
3414 case BLRAA:
3415 case BLRAB:
3416 case BLRAAZ:
3417 case BLRABZ:
3418 return BranchAndLink;
3419 case BR:
3420 case BRAA:
3421 case BRAB:
3422 case BRAAZ:
3423 case BRABZ:
3424 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3425 !PcIsInGuardedPage()) {
3426 return BranchFromUnguardedOrToIP;
3427 }
3428 return BranchFromGuardedNotToIP;
3429 }
3430 return DefaultBType;
3431}
Alexandre Ramesd3832962016-07-04 15:03:43 +01003432
3433void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003434 bool authenticate = false;
3435 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01003436 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01003437 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003438
3439 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3440 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01003441 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003442 VIXL_FALLTHROUGH();
3443 case BR:
3444 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01003445 break;
3446
3447 case BLRAAZ:
3448 case BLRABZ:
3449 link = true;
3450 VIXL_FALLTHROUGH();
3451 case BRAAZ:
3452 case BRABZ:
3453 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003454 break;
3455
3456 case BLRAA:
3457 case BLRAB:
3458 link = true;
3459 VIXL_FALLTHROUGH();
3460 case BRAA:
3461 case BRAB:
3462 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003463 context = ReadXRegister(instr->GetRd());
3464 break;
3465
3466 case RETAA:
3467 case RETAB:
3468 authenticate = true;
3469 addr = ReadXRegister(kLinkRegCode);
3470 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003471 break;
3472 default:
3473 VIXL_UNREACHABLE();
3474 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003475
3476 if (link) {
3477 WriteLr(instr->GetNextInstruction());
3478 }
3479
3480 if (authenticate) {
3481 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3482 addr = AuthPAC(addr, context, key, kInstructionPointer);
3483
3484 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3485 if (((addr >> error_lsb) & 0x3) != 0x0) {
3486 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3487 }
3488 }
3489
Martyn Capewellcb963f72018-10-22 15:25:28 +01003490 WritePc(Instruction::Cast(addr));
3491 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003492}
3493
3494
3495void Simulator::VisitTestBranch(const Instruction* instr) {
3496 unsigned bit_pos =
3497 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3498 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3499 bool take_branch = false;
3500 switch (instr->Mask(TestBranchMask)) {
3501 case TBZ:
3502 take_branch = bit_zero;
3503 break;
3504 case TBNZ:
3505 take_branch = !bit_zero;
3506 break;
3507 default:
3508 VIXL_UNIMPLEMENTED();
3509 }
3510 if (take_branch) {
3511 WritePc(instr->GetImmPCOffsetTarget());
3512 }
3513}
3514
3515
3516void Simulator::VisitCompareBranch(const Instruction* instr) {
3517 unsigned rt = instr->GetRt();
3518 bool take_branch = false;
3519 switch (instr->Mask(CompareBranchMask)) {
3520 case CBZ_w:
3521 take_branch = (ReadWRegister(rt) == 0);
3522 break;
3523 case CBZ_x:
3524 take_branch = (ReadXRegister(rt) == 0);
3525 break;
3526 case CBNZ_w:
3527 take_branch = (ReadWRegister(rt) != 0);
3528 break;
3529 case CBNZ_x:
3530 take_branch = (ReadXRegister(rt) != 0);
3531 break;
3532 default:
3533 VIXL_UNIMPLEMENTED();
3534 }
3535 if (take_branch) {
3536 WritePc(instr->GetImmPCOffsetTarget());
3537 }
3538}
3539
3540
3541void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3542 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3543 bool set_flags = instr->GetFlagsUpdate();
3544 int64_t new_val = 0;
3545 Instr operation = instr->Mask(AddSubOpMask);
3546
3547 switch (operation) {
3548 case ADD:
3549 case ADDS: {
3550 new_val = AddWithCarry(reg_size,
3551 set_flags,
3552 ReadRegister(reg_size,
3553 instr->GetRn(),
3554 instr->GetRnMode()),
3555 op2);
3556 break;
3557 }
3558 case SUB:
3559 case SUBS: {
3560 new_val = AddWithCarry(reg_size,
3561 set_flags,
3562 ReadRegister(reg_size,
3563 instr->GetRn(),
3564 instr->GetRnMode()),
3565 ~op2,
3566 1);
3567 break;
3568 }
3569 default:
3570 VIXL_UNREACHABLE();
3571 }
3572
3573 WriteRegister(reg_size,
3574 instr->GetRd(),
3575 new_val,
3576 LogRegWrites,
3577 instr->GetRdMode());
3578}
3579
3580
3581void Simulator::VisitAddSubShifted(const Instruction* instr) {
3582 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3583 int64_t op2 = ShiftOperand(reg_size,
3584 ReadRegister(reg_size, instr->GetRm()),
3585 static_cast<Shift>(instr->GetShiftDP()),
3586 instr->GetImmDPShift());
3587 AddSubHelper(instr, op2);
3588}
3589
3590
3591void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3592 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01003593 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003594 AddSubHelper(instr, op2);
3595}
3596
3597
3598void Simulator::VisitAddSubExtended(const Instruction* instr) {
3599 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3600 int64_t op2 = ExtendValue(reg_size,
3601 ReadRegister(reg_size, instr->GetRm()),
3602 static_cast<Extend>(instr->GetExtendMode()),
3603 instr->GetImmExtendShift());
3604 AddSubHelper(instr, op2);
3605}
3606
3607
3608void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3609 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3610 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3611 int64_t new_val;
3612
3613 if ((instr->Mask(AddSubOpMask) == SUB) ||
3614 (instr->Mask(AddSubOpMask) == SUBS)) {
3615 op2 = ~op2;
3616 }
3617
3618 new_val = AddWithCarry(reg_size,
3619 instr->GetFlagsUpdate(),
3620 ReadRegister(reg_size, instr->GetRn()),
3621 op2,
3622 ReadC());
3623
3624 WriteRegister(reg_size, instr->GetRd(), new_val);
3625}
3626
3627
Alexander Gilday2487f142018-11-05 13:07:27 +00003628void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3629 switch (instr->Mask(RotateRightIntoFlagsMask)) {
3630 case RMIF: {
3631 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3632 unsigned shift = instr->GetImmRMIFRotation();
3633 unsigned mask = instr->GetNzcv();
3634 uint64_t rotated = RotateRight(value, shift, kXRegSize);
3635
3636 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3637 break;
3638 }
3639 }
3640}
3641
3642
3643void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3644 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3645 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3646
3647 unsigned sign_bit = (value >> msb) & 1;
3648 unsigned overflow_bit = (value >> (msb + 1)) & 1;
3649 ReadNzcv().SetN(sign_bit);
3650 ReadNzcv().SetZ((value << (31 - msb)) == 0);
3651 ReadNzcv().SetV(sign_bit ^ overflow_bit);
3652}
3653
3654
Alexandre Ramesd3832962016-07-04 15:03:43 +01003655void Simulator::VisitLogicalShifted(const Instruction* instr) {
3656 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3657 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3658 unsigned shift_amount = instr->GetImmDPShift();
3659 int64_t op2 = ShiftOperand(reg_size,
3660 ReadRegister(reg_size, instr->GetRm()),
3661 shift_type,
3662 shift_amount);
3663 if (instr->Mask(NOT) == NOT) {
3664 op2 = ~op2;
3665 }
3666 LogicalHelper(instr, op2);
3667}
3668
3669
3670void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3671 LogicalHelper(instr, instr->GetImmLogical());
3672}
3673
3674
3675void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3676 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3677 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3678 int64_t result = 0;
3679 bool update_flags = false;
3680
3681 // Switch on the logical operation, stripping out the NOT bit, as it has a
3682 // different meaning for logical immediate instructions.
3683 switch (instr->Mask(LogicalOpMask & ~NOT)) {
3684 case ANDS:
3685 update_flags = true;
3686 VIXL_FALLTHROUGH();
3687 case AND:
3688 result = op1 & op2;
3689 break;
3690 case ORR:
3691 result = op1 | op2;
3692 break;
3693 case EOR:
3694 result = op1 ^ op2;
3695 break;
3696 default:
3697 VIXL_UNIMPLEMENTED();
3698 }
3699
3700 if (update_flags) {
3701 ReadNzcv().SetN(CalcNFlag(result, reg_size));
3702 ReadNzcv().SetZ(CalcZFlag(result));
3703 ReadNzcv().SetC(0);
3704 ReadNzcv().SetV(0);
3705 LogSystemRegister(NZCV);
3706 }
3707
3708 WriteRegister(reg_size,
3709 instr->GetRd(),
3710 result,
3711 LogRegWrites,
3712 instr->GetRdMode());
3713}
3714
3715
3716void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3717 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3718 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3719}
3720
3721
3722void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3723 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3724}
3725
3726
3727void Simulator::ConditionalCompareHelper(const Instruction* instr,
3728 int64_t op2) {
3729 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3730 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3731
3732 if (ConditionPassed(instr->GetCondition())) {
3733 // If the condition passes, set the status flags to the result of comparing
3734 // the operands.
3735 if (instr->Mask(ConditionalCompareMask) == CCMP) {
3736 AddWithCarry(reg_size, true, op1, ~op2, 1);
3737 } else {
3738 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3739 AddWithCarry(reg_size, true, op1, op2, 0);
3740 }
3741 } else {
3742 // If the condition fails, set the status flags to the nzcv immediate.
3743 ReadNzcv().SetFlags(instr->GetNzcv());
3744 LogSystemRegister(NZCV);
3745 }
3746}
3747
3748
3749void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3750 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3751 LoadStoreHelper(instr, offset, Offset);
3752}
3753
3754
3755void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3756 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3757}
3758
3759
3760void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3761 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3762}
3763
3764
3765void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3766 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3767}
3768
3769
Alexander Gilday311edf22018-10-29 13:41:41 +00003770template <typename T1, typename T2>
3771void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
3772 unsigned rt = instr->GetRt();
3773 unsigned rn = instr->GetRn();
3774
3775 unsigned element_size = sizeof(T2);
3776 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3777 int offset = instr->GetImmLS();
3778 address += offset;
3779
3780 // Verify that the address is available to the host.
3781 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3782
3783 // Check the alignment of `address`.
3784 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3785 VIXL_ALIGNMENT_EXCEPTION();
3786 }
3787
3788 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
3789
3790 // Approximate load-acquire by issuing a full barrier after the load.
3791 __sync_synchronize();
3792
Jacob Bramley423e5422019-11-13 19:15:55 +00003793 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003794}
3795
3796
3797template <typename T>
3798void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
3799 unsigned rt = instr->GetRt();
3800 unsigned rn = instr->GetRn();
3801
3802 unsigned element_size = sizeof(T);
3803 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3804 int offset = instr->GetImmLS();
3805 address += offset;
3806
3807 // Verify that the address is available to the host.
3808 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3809
3810 // Check the alignment of `address`.
3811 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3812 VIXL_ALIGNMENT_EXCEPTION();
3813 }
3814
3815 // Approximate store-release by issuing a full barrier after the load.
3816 __sync_synchronize();
3817
3818 Memory::Write<T>(address, ReadRegister<T>(rt));
3819
Jacob Bramley423e5422019-11-13 19:15:55 +00003820 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003821}
3822
3823
3824void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
3825 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
3826 case LDAPURB:
3827 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
3828 break;
3829 case LDAPURH:
3830 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
3831 break;
3832 case LDAPUR_w:
3833 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
3834 break;
3835 case LDAPUR_x:
3836 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
3837 break;
3838 case LDAPURSB_w:
3839 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
3840 break;
3841 case LDAPURSB_x:
3842 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
3843 break;
3844 case LDAPURSH_w:
3845 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
3846 break;
3847 case LDAPURSH_x:
3848 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
3849 break;
3850 case LDAPURSW:
3851 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
3852 break;
3853 case STLURB:
3854 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
3855 break;
3856 case STLURH:
3857 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
3858 break;
3859 case STLUR_w:
3860 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
3861 break;
3862 case STLUR_x:
3863 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
3864 break;
3865 }
3866}
3867
3868
Alexander Gilday75605592018-11-01 09:30:29 +00003869void Simulator::VisitLoadStorePAC(const Instruction* instr) {
3870 unsigned dst = instr->GetRt();
3871 unsigned addr_reg = instr->GetRn();
3872
3873 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
3874
3875 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
3876 address = AuthPAC(address, 0, key, kDataPointer);
3877
3878 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
3879 if (((address >> error_lsb) & 0x3) != 0x0) {
3880 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3881 }
3882
3883
3884 if ((addr_reg == 31) && ((address % 16) != 0)) {
3885 // When the base register is SP the stack pointer is required to be
3886 // quadword aligned prior to the address calculation and write-backs.
3887 // Misalignment will cause a stack alignment fault.
3888 VIXL_ALIGNMENT_EXCEPTION();
3889 }
3890
3891 int64_t offset = instr->GetImmLSPAC();
3892 address += offset;
3893
3894 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
3895 // Pre-index mode.
3896 VIXL_ASSERT(offset != 0);
3897 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
3898 }
3899
3900 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
3901
3902 // Verify that the calculated address is available to the host.
3903 VIXL_ASSERT(address == addr_ptr);
3904
3905 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
3906 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00003907 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00003908}
3909
3910
Alexandre Ramesd3832962016-07-04 15:03:43 +01003911void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
3912 Extend ext = static_cast<Extend>(instr->GetExtendMode());
3913 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
3914 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
3915
3916 int64_t offset =
3917 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
3918 LoadStoreHelper(instr, offset, Offset);
3919}
3920
3921
3922void Simulator::LoadStoreHelper(const Instruction* instr,
3923 int64_t offset,
3924 AddrMode addrmode) {
3925 unsigned srcdst = instr->GetRt();
3926 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
3927
Jacob Bramley423e5422019-11-13 19:15:55 +00003928 bool rt_is_vreg = false;
3929 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003930 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
3931 switch (op) {
3932 case LDRB_w:
3933 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003934 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003935 break;
3936 case LDRH_w:
3937 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003938 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003939 break;
3940 case LDR_w:
3941 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003942 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003943 break;
3944 case LDR_x:
3945 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003946 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003947 break;
3948 case LDRSB_w:
3949 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003950 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003951 break;
3952 case LDRSH_w:
3953 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003954 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003955 break;
3956 case LDRSB_x:
3957 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003958 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003959 break;
3960 case LDRSH_x:
3961 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003962 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003963 break;
3964 case LDRSW_x:
3965 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003966 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003967 break;
3968 case LDR_b:
3969 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003970 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003971 break;
3972 case LDR_h:
3973 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003974 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003975 break;
3976 case LDR_s:
3977 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003978 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003979 break;
3980 case LDR_d:
3981 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003982 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003983 break;
3984 case LDR_q:
3985 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003986 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003987 break;
3988
3989 case STRB_w:
3990 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
3991 break;
3992 case STRH_w:
3993 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
3994 break;
3995 case STR_w:
3996 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
3997 break;
3998 case STR_x:
3999 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
4000 break;
4001 case STR_b:
4002 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004003 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004004 break;
4005 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01004006 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004007 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004008 break;
4009 case STR_s:
4010 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004011 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004012 break;
4013 case STR_d:
4014 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004015 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004016 break;
4017 case STR_q:
4018 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004019 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004020 break;
4021
4022 // Ignore prfm hint instructions.
4023 case PRFM:
4024 break;
4025
4026 default:
4027 VIXL_UNIMPLEMENTED();
4028 }
4029
Jacob Bramley423e5422019-11-13 19:15:55 +00004030 // Print a detailed trace (including the memory address).
4031 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004032 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00004033 unsigned result_size = extend ? extend_to_size : access_size;
4034 PrintRegisterFormat print_format =
4035 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4036 : GetPrintRegisterFormatForSize(result_size);
4037
Alexandre Ramesd3832962016-07-04 15:03:43 +01004038 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004039 if (rt_is_vreg) {
4040 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004041 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004042 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004043 }
4044 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004045 if (rt_is_vreg) {
4046 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004047 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004048 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004049 }
4050 } else {
4051 VIXL_ASSERT(op == PRFM);
4052 }
4053
4054 local_monitor_.MaybeClear();
4055}
4056
4057
4058void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4059 LoadStorePairHelper(instr, Offset);
4060}
4061
4062
4063void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4064 LoadStorePairHelper(instr, PreIndex);
4065}
4066
4067
4068void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4069 LoadStorePairHelper(instr, PostIndex);
4070}
4071
4072
4073void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4074 LoadStorePairHelper(instr, Offset);
4075}
4076
4077
4078void Simulator::LoadStorePairHelper(const Instruction* instr,
4079 AddrMode addrmode) {
4080 unsigned rt = instr->GetRt();
4081 unsigned rt2 = instr->GetRt2();
4082 int element_size = 1 << instr->GetSizeLSPair();
4083 int64_t offset = instr->GetImmLSPair() * element_size;
4084 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4085 uintptr_t address2 = address + element_size;
4086
4087 LoadStorePairOp op =
4088 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4089
4090 // 'rt' and 'rt2' can only be aliased for stores.
4091 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4092
Jacob Bramley423e5422019-11-13 19:15:55 +00004093 bool rt_is_vreg = false;
4094 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004095 switch (op) {
4096 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4097 // will print a more detailed log.
4098 case LDP_w: {
4099 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4100 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
4101 break;
4102 }
4103 case LDP_s: {
4104 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
4105 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004106 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004107 break;
4108 }
4109 case LDP_x: {
4110 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4111 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
4112 break;
4113 }
4114 case LDP_d: {
4115 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
4116 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004117 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004118 break;
4119 }
4120 case LDP_q: {
4121 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
4122 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004123 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 break;
4125 }
4126 case LDPSW_x: {
4127 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
4128 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004129 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004130 break;
4131 }
4132 case STP_w: {
4133 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4134 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
4135 break;
4136 }
4137 case STP_s: {
4138 Memory::Write<float>(address, ReadSRegister(rt));
4139 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004140 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004141 break;
4142 }
4143 case STP_x: {
4144 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4145 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
4146 break;
4147 }
4148 case STP_d: {
4149 Memory::Write<double>(address, ReadDRegister(rt));
4150 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004151 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004152 break;
4153 }
4154 case STP_q: {
4155 Memory::Write<qreg_t>(address, ReadQRegister(rt));
4156 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004157 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004158 break;
4159 }
4160 default:
4161 VIXL_UNREACHABLE();
4162 }
4163
Jacob Bramley423e5422019-11-13 19:15:55 +00004164 // Print a detailed trace (including the memory address).
4165 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4166 PrintRegisterFormat print_format =
4167 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4168 : GetPrintRegisterFormatForSize(result_size);
4169
Alexandre Ramesd3832962016-07-04 15:03:43 +01004170 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004171 if (rt_is_vreg) {
4172 LogVRead(rt, print_format, address);
4173 LogVRead(rt2, print_format, address2);
4174 } else if (sign_extend) {
4175 LogExtendingRead(rt, print_format, element_size, address);
4176 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004177 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004178 LogRead(rt, print_format, address);
4179 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004180 }
4181 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004182 if (rt_is_vreg) {
4183 LogVWrite(rt, print_format, address);
4184 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004185 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004186 LogWrite(rt, print_format, address);
4187 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004188 }
4189 }
4190
4191 local_monitor_.MaybeClear();
4192}
4193
4194
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004195template <typename T>
4196void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4197 unsigned rs = instr->GetRs();
4198 unsigned rt = instr->GetRt();
4199 unsigned rn = instr->GetRn();
4200
4201 unsigned element_size = sizeof(T);
4202 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4203
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004204 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4205
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004206 bool is_acquire = instr->ExtractBit(22) == 1;
4207 bool is_release = instr->ExtractBit(15) == 1;
4208
4209 T comparevalue = ReadRegister<T>(rs);
4210 T newvalue = ReadRegister<T>(rt);
4211
4212 // The architecture permits that the data read clears any exclusive monitors
4213 // associated with that location, even if the compare subsequently fails.
4214 local_monitor_.Clear();
4215
4216 T data = Memory::Read<T>(address);
4217 if (is_acquire) {
4218 // Approximate load-acquire by issuing a full barrier after the load.
4219 __sync_synchronize();
4220 }
4221
4222 if (data == comparevalue) {
4223 if (is_release) {
4224 // Approximate store-release by issuing a full barrier before the store.
4225 __sync_synchronize();
4226 }
4227 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00004228 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004229 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004230 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004231 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004232}
4233
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004234
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004235template <typename T>
4236void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4237 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4238 unsigned rs = instr->GetRs();
4239 unsigned rt = instr->GetRt();
4240 unsigned rn = instr->GetRn();
4241
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004242 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004243
4244 unsigned element_size = sizeof(T);
4245 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004246
4247 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4248
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004249 uint64_t address2 = address + element_size;
4250
4251 bool is_acquire = instr->ExtractBit(22) == 1;
4252 bool is_release = instr->ExtractBit(15) == 1;
4253
4254 T comparevalue_high = ReadRegister<T>(rs + 1);
4255 T comparevalue_low = ReadRegister<T>(rs);
4256 T newvalue_high = ReadRegister<T>(rt + 1);
4257 T newvalue_low = ReadRegister<T>(rt);
4258
4259 // The architecture permits that the data read clears any exclusive monitors
4260 // associated with that location, even if the compare subsequently fails.
4261 local_monitor_.Clear();
4262
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004263 T data_low = Memory::Read<T>(address);
4264 T data_high = Memory::Read<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004265
4266 if (is_acquire) {
4267 // Approximate load-acquire by issuing a full barrier after the load.
4268 __sync_synchronize();
4269 }
4270
4271 bool same =
4272 (data_high == comparevalue_high) && (data_low == comparevalue_low);
4273 if (same) {
4274 if (is_release) {
4275 // Approximate store-release by issuing a full barrier before the store.
4276 __sync_synchronize();
4277 }
4278
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004279 Memory::Write<T>(address, newvalue_low);
4280 Memory::Write<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004281 }
4282
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004283 WriteRegister<T>(rs + 1, data_high, NoRegLog);
4284 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004285
Jacob Bramley423e5422019-11-13 19:15:55 +00004286 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004287 LogRead(rs, format, address);
4288 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004289
4290 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004291 LogWrite(rt, format, address);
4292 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004293 }
4294}
4295
Jacob Bramley85a9c102019-12-09 17:48:29 +00004296bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4297 // To simulate fault-tolerant loads, we need to know what host addresses we
4298 // can access without generating a real fault. One way to do that is to
4299 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
4300 // and less intrusive than using (global) signal handlers.
4301 //
4302 // [1]: https://stackoverflow.com/questions/7134590
4303
4304 size_t written = 0;
4305 bool can_read = true;
4306 // `write` will normally return after one invocation, but it is allowed to
4307 // handle only part of the operation, so wrap it in a loop.
4308 while (can_read && (written < size)) {
4309 ssize_t result = write(dummy_pipe_fd_[1],
4310 reinterpret_cast<void*>(address + written),
4311 size - written);
4312 if (result > 0) {
4313 written += result;
4314 } else {
4315 switch (result) {
4316 case -EPERM:
4317 case -EFAULT:
4318 // The address range is not accessible.
4319 // `write` is supposed to return -EFAULT in this case, but in practice
4320 // it seems to return -EPERM, so we accept that too.
4321 can_read = false;
4322 break;
4323 case -EINTR:
4324 // The call was interrupted by a signal. Just try again.
4325 break;
4326 default:
4327 // Any other error is fatal.
4328 VIXL_ABORT();
4329 }
4330 }
4331 }
4332 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4333 // the dummy data is buffered. As before, we expect to drain the whole write
4334 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
4335 // function is primarily intended to implement SVE fault-tolerant loads, so
4336 // the maximum Z register size is a good default buffer size.
4337 char buffer[kZRegMaxSizeInBytes];
4338 while (written > 0) {
4339 ssize_t result = read(dummy_pipe_fd_[0],
4340 reinterpret_cast<void*>(buffer),
4341 sizeof(buffer));
4342 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4343 // we've read everything that was written, so treat 0 as an error.
4344 if (result > 0) {
4345 VIXL_ASSERT(static_cast<size_t>(result) <= written);
4346 written -= result;
4347 } else {
4348 // For -EINTR, just try again. We can't handle any other error.
4349 VIXL_CHECK(result == -EINTR);
4350 }
4351 }
4352
4353 return can_read;
4354}
Alexandre Ramesd3832962016-07-04 15:03:43 +01004355
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004356void Simulator::PrintExclusiveAccessWarning() {
4357 if (print_exclusive_access_warning_) {
4358 fprintf(stderr,
4359 "%sWARNING:%s VIXL simulator support for "
4360 "load-/store-/clear-exclusive "
4361 "instructions is limited. Refer to the README for details.%s\n",
4362 clr_warning,
4363 clr_warning_message,
4364 clr_normal);
4365 print_exclusive_access_warning_ = false;
4366 }
4367}
4368
Alexandre Ramesd3832962016-07-04 15:03:43 +01004369void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004370 LoadStoreExclusive op =
4371 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4372
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004373 switch (op) {
4374 case CAS_w:
4375 case CASA_w:
4376 case CASL_w:
4377 case CASAL_w:
4378 CompareAndSwapHelper<uint32_t>(instr);
4379 break;
4380 case CAS_x:
4381 case CASA_x:
4382 case CASL_x:
4383 case CASAL_x:
4384 CompareAndSwapHelper<uint64_t>(instr);
4385 break;
4386 case CASB:
4387 case CASAB:
4388 case CASLB:
4389 case CASALB:
4390 CompareAndSwapHelper<uint8_t>(instr);
4391 break;
4392 case CASH:
4393 case CASAH:
4394 case CASLH:
4395 case CASALH:
4396 CompareAndSwapHelper<uint16_t>(instr);
4397 break;
4398 case CASP_w:
4399 case CASPA_w:
4400 case CASPL_w:
4401 case CASPAL_w:
4402 CompareAndSwapPairHelper<uint32_t>(instr);
4403 break;
4404 case CASP_x:
4405 case CASPA_x:
4406 case CASPL_x:
4407 case CASPAL_x:
4408 CompareAndSwapPairHelper<uint64_t>(instr);
4409 break;
4410 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004411 PrintExclusiveAccessWarning();
4412
4413 unsigned rs = instr->GetRs();
4414 unsigned rt = instr->GetRt();
4415 unsigned rt2 = instr->GetRt2();
4416 unsigned rn = instr->GetRn();
4417
4418 bool is_exclusive = !instr->GetLdStXNotExclusive();
4419 bool is_acquire_release =
4420 !is_exclusive || instr->GetLdStXAcquireRelease();
4421 bool is_load = instr->GetLdStXLoad();
4422 bool is_pair = instr->GetLdStXPair();
4423
4424 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4425 unsigned access_size = is_pair ? element_size * 2 : element_size;
4426 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4427
4428 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4429
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004430 if (is_load) {
4431 if (is_exclusive) {
4432 local_monitor_.MarkExclusive(address, access_size);
4433 } else {
4434 // Any non-exclusive load can clear the local monitor as a side
4435 // effect. We don't need to do this, but it is useful to stress the
4436 // simulated code.
4437 local_monitor_.Clear();
4438 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004439
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004440 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4441 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00004442 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004443 switch (op) {
4444 case LDXRB_w:
4445 case LDAXRB_w:
4446 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004447 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004448 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004449 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004450 break;
4451 case LDXRH_w:
4452 case LDAXRH_w:
4453 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004454 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004455 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004456 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004457 break;
4458 case LDXR_w:
4459 case LDAXR_w:
4460 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004461 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004462 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004463 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004464 break;
4465 case LDXR_x:
4466 case LDAXR_x:
4467 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004468 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004469 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004470 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004471 break;
4472 case LDXP_w:
4473 case LDAXP_w:
4474 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4475 WriteWRegister(rt2,
4476 Memory::Read<uint32_t>(address + element_size),
4477 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004478 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004479 break;
4480 case LDXP_x:
4481 case LDAXP_x:
4482 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4483 WriteXRegister(rt2,
4484 Memory::Read<uint64_t>(address + element_size),
4485 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004486 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004487 break;
4488 default:
4489 VIXL_UNREACHABLE();
4490 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004491
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004492 if (is_acquire_release) {
4493 // Approximate load-acquire by issuing a full barrier after the load.
4494 __sync_synchronize();
4495 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004496
Jacob Bramley423e5422019-11-13 19:15:55 +00004497 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4498 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004499 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004500 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004501 }
4502 } else {
4503 if (is_acquire_release) {
4504 // Approximate store-release by issuing a full barrier before the
4505 // store.
4506 __sync_synchronize();
4507 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004508
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004509 bool do_store = true;
4510 if (is_exclusive) {
4511 do_store = local_monitor_.IsExclusive(address, access_size) &&
4512 global_monitor_.IsExclusive(address, access_size);
4513 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004514
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004515 // - All exclusive stores explicitly clear the local monitor.
4516 local_monitor_.Clear();
4517 } else {
4518 // - Any other store can clear the local monitor as a side effect.
4519 local_monitor_.MaybeClear();
4520 }
4521
4522 if (do_store) {
4523 switch (op) {
4524 case STXRB_w:
4525 case STLXRB_w:
4526 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004527 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004528 Memory::Write<uint8_t>(address, ReadWRegister(rt));
4529 break;
4530 case STXRH_w:
4531 case STLXRH_w:
4532 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004533 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004534 Memory::Write<uint16_t>(address, ReadWRegister(rt));
4535 break;
4536 case STXR_w:
4537 case STLXR_w:
4538 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004539 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004540 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4541 break;
4542 case STXR_x:
4543 case STLXR_x:
4544 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004545 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004546 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4547 break;
4548 case STXP_w:
4549 case STLXP_w:
4550 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4551 Memory::Write<uint32_t>(address + element_size,
4552 ReadWRegister(rt2));
4553 break;
4554 case STXP_x:
4555 case STLXP_x:
4556 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4557 Memory::Write<uint64_t>(address + element_size,
4558 ReadXRegister(rt2));
4559 break;
4560 default:
4561 VIXL_UNREACHABLE();
4562 }
4563
Jacob Bramley423e5422019-11-13 19:15:55 +00004564 PrintRegisterFormat format =
4565 GetPrintRegisterFormatForSize(element_size);
4566 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004567 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004568 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004569 }
4570 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004571 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004572 }
4573}
4574
Jacob Bramleyca789742018-09-13 14:25:46 +01004575template <typename T>
4576void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4577 unsigned rs = instr->GetRs();
4578 unsigned rt = instr->GetRt();
4579 unsigned rn = instr->GetRn();
4580
4581 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4582 bool is_release = instr->ExtractBit(22) == 1;
4583
4584 unsigned element_size = sizeof(T);
4585 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4586
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004587 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004588
4589 T value = ReadRegister<T>(rs);
4590
4591 T data = Memory::Read<T>(address);
4592
4593 if (is_acquire) {
4594 // Approximate load-acquire by issuing a full barrier after the load.
4595 __sync_synchronize();
4596 }
4597
4598 T result = 0;
4599 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4600 case LDADDOp:
4601 result = data + value;
4602 break;
4603 case LDCLROp:
4604 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4605 result = data & ~value;
4606 break;
4607 case LDEOROp:
4608 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4609 result = data ^ value;
4610 break;
4611 case LDSETOp:
4612 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4613 result = data | value;
4614 break;
4615
4616 // Signed/Unsigned difference is done via the templated type T.
4617 case LDSMAXOp:
4618 case LDUMAXOp:
4619 result = (data > value) ? data : value;
4620 break;
4621 case LDSMINOp:
4622 case LDUMINOp:
4623 result = (data > value) ? value : data;
4624 break;
4625 }
4626
4627 if (is_release) {
4628 // Approximate store-release by issuing a full barrier before the store.
4629 __sync_synchronize();
4630 }
4631
4632 Memory::Write<T>(address, result);
4633 WriteRegister<T>(rt, data, NoRegLog);
4634
Jacob Bramley423e5422019-11-13 19:15:55 +00004635 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4636 LogRead(rt, format, address);
4637 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004638}
4639
4640template <typename T>
4641void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4642 unsigned rs = instr->GetRs();
4643 unsigned rt = instr->GetRt();
4644 unsigned rn = instr->GetRn();
4645
4646 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4647 bool is_release = instr->ExtractBit(22) == 1;
4648
4649 unsigned element_size = sizeof(T);
4650 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4651
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004652 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004653
4654 T data = Memory::Read<T>(address);
4655 if (is_acquire) {
4656 // Approximate load-acquire by issuing a full barrier after the load.
4657 __sync_synchronize();
4658 }
4659
4660 if (is_release) {
4661 // Approximate store-release by issuing a full barrier before the store.
4662 __sync_synchronize();
4663 }
4664 Memory::Write<T>(address, ReadRegister<T>(rs));
4665
4666 WriteRegister<T>(rt, data);
4667
Jacob Bramley423e5422019-11-13 19:15:55 +00004668 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4669 LogRead(rt, format, address);
4670 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004671}
4672
4673template <typename T>
4674void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4675 unsigned rt = instr->GetRt();
4676 unsigned rn = instr->GetRn();
4677
4678 unsigned element_size = sizeof(T);
4679 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4680
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004681 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4682
Jacob Bramleyca789742018-09-13 14:25:46 +01004683 WriteRegister<T>(rt, Memory::Read<T>(address));
4684
4685 // Approximate load-acquire by issuing a full barrier after the load.
4686 __sync_synchronize();
4687
Jacob Bramley423e5422019-11-13 19:15:55 +00004688 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004689}
4690
4691#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4692 V(LDADD) \
4693 V(LDCLR) \
4694 V(LDEOR) \
4695 V(LDSET) \
4696 V(LDUMAX) \
4697 V(LDUMIN)
4698
4699#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4700 V(LDSMAX) \
4701 V(LDSMIN)
4702
4703void Simulator::VisitAtomicMemory(const Instruction* instr) {
4704 switch (instr->Mask(AtomicMemoryMask)) {
4705// clang-format off
4706#define SIM_FUNC_B(A) \
4707 case A##B: \
4708 case A##AB: \
4709 case A##LB: \
4710 case A##ALB:
4711#define SIM_FUNC_H(A) \
4712 case A##H: \
4713 case A##AH: \
4714 case A##LH: \
4715 case A##ALH:
4716#define SIM_FUNC_w(A) \
4717 case A##_w: \
4718 case A##A_w: \
4719 case A##L_w: \
4720 case A##AL_w:
4721#define SIM_FUNC_x(A) \
4722 case A##_x: \
4723 case A##A_x: \
4724 case A##L_x: \
4725 case A##AL_x:
4726
4727 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4728 AtomicMemorySimpleHelper<uint8_t>(instr);
4729 break;
4730 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4731 AtomicMemorySimpleHelper<int8_t>(instr);
4732 break;
4733 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4734 AtomicMemorySimpleHelper<uint16_t>(instr);
4735 break;
4736 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4737 AtomicMemorySimpleHelper<int16_t>(instr);
4738 break;
4739 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4740 AtomicMemorySimpleHelper<uint32_t>(instr);
4741 break;
4742 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4743 AtomicMemorySimpleHelper<int32_t>(instr);
4744 break;
4745 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4746 AtomicMemorySimpleHelper<uint64_t>(instr);
4747 break;
4748 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4749 AtomicMemorySimpleHelper<int64_t>(instr);
4750 break;
4751 // clang-format on
4752
4753 case SWPB:
4754 case SWPAB:
4755 case SWPLB:
4756 case SWPALB:
4757 AtomicMemorySwapHelper<uint8_t>(instr);
4758 break;
4759 case SWPH:
4760 case SWPAH:
4761 case SWPLH:
4762 case SWPALH:
4763 AtomicMemorySwapHelper<uint16_t>(instr);
4764 break;
4765 case SWP_w:
4766 case SWPA_w:
4767 case SWPL_w:
4768 case SWPAL_w:
4769 AtomicMemorySwapHelper<uint32_t>(instr);
4770 break;
4771 case SWP_x:
4772 case SWPA_x:
4773 case SWPL_x:
4774 case SWPAL_x:
4775 AtomicMemorySwapHelper<uint64_t>(instr);
4776 break;
4777 case LDAPRB:
4778 LoadAcquireRCpcHelper<uint8_t>(instr);
4779 break;
4780 case LDAPRH:
4781 LoadAcquireRCpcHelper<uint16_t>(instr);
4782 break;
4783 case LDAPR_w:
4784 LoadAcquireRCpcHelper<uint32_t>(instr);
4785 break;
4786 case LDAPR_x:
4787 LoadAcquireRCpcHelper<uint64_t>(instr);
4788 break;
4789 }
4790}
4791
Alexandre Ramesd3832962016-07-04 15:03:43 +01004792
4793void Simulator::VisitLoadLiteral(const Instruction* instr) {
4794 unsigned rt = instr->GetRt();
4795 uint64_t address = instr->GetLiteralAddress<uint64_t>();
4796
4797 // Verify that the calculated address is available to the host.
4798 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4799
4800 switch (instr->Mask(LoadLiteralMask)) {
4801 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
4802 // print a more detailed log.
4803 case LDR_w_lit:
4804 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004805 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004806 break;
4807 case LDR_x_lit:
4808 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004809 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004810 break;
4811 case LDR_s_lit:
4812 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004813 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004814 break;
4815 case LDR_d_lit:
4816 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004817 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004818 break;
4819 case LDR_q_lit:
4820 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004821 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004822 break;
4823 case LDRSW_x_lit:
4824 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004825 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004826 break;
4827
4828 // Ignore prfm hint instructions.
4829 case PRFM_lit:
4830 break;
4831
4832 default:
4833 VIXL_UNREACHABLE();
4834 }
4835
4836 local_monitor_.MaybeClear();
4837}
4838
4839
4840uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
4841 int64_t offset,
4842 AddrMode addrmode) {
4843 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4844
4845 if ((addr_reg == 31) && ((address % 16) != 0)) {
4846 // When the base register is SP the stack pointer is required to be
4847 // quadword aligned prior to the address calculation and write-backs.
4848 // Misalignment will cause a stack alignment fault.
4849 VIXL_ALIGNMENT_EXCEPTION();
4850 }
4851
4852 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
4853 VIXL_ASSERT(offset != 0);
4854 // Only preindex should log the register update here. For Postindex, the
4855 // update will be printed automatically by LogWrittenRegisters _after_ the
4856 // memory access itself is logged.
4857 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
4858 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
4859 }
4860
4861 if ((addrmode == Offset) || (addrmode == PreIndex)) {
4862 address += offset;
4863 }
4864
4865 // Verify that the calculated address is available to the host.
4866 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4867
4868 return static_cast<uintptr_t>(address);
4869}
4870
4871
4872void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
4873 MoveWideImmediateOp mov_op =
4874 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
4875 int64_t new_xn_val = 0;
4876
4877 bool is_64_bits = instr->GetSixtyFourBits() == 1;
4878 // Shift is limited for W operations.
4879 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
4880
4881 // Get the shifted immediate.
4882 int64_t shift = instr->GetShiftMoveWide() * 16;
4883 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
4884 << shift;
4885
4886 // Compute the new value.
4887 switch (mov_op) {
4888 case MOVN_w:
4889 case MOVN_x: {
4890 new_xn_val = ~shifted_imm16;
4891 if (!is_64_bits) new_xn_val &= kWRegMask;
4892 break;
4893 }
4894 case MOVK_w:
4895 case MOVK_x: {
4896 unsigned reg_code = instr->GetRd();
4897 int64_t prev_xn_val =
4898 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
4899 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
4900 break;
4901 }
4902 case MOVZ_w:
4903 case MOVZ_x: {
4904 new_xn_val = shifted_imm16;
4905 break;
4906 }
4907 default:
4908 VIXL_UNREACHABLE();
4909 }
4910
4911 // Update the destination register.
4912 WriteXRegister(instr->GetRd(), new_xn_val);
4913}
4914
4915
4916void Simulator::VisitConditionalSelect(const Instruction* instr) {
4917 uint64_t new_val = ReadXRegister(instr->GetRn());
4918
4919 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
4920 new_val = ReadXRegister(instr->GetRm());
4921 switch (instr->Mask(ConditionalSelectMask)) {
4922 case CSEL_w:
4923 case CSEL_x:
4924 break;
4925 case CSINC_w:
4926 case CSINC_x:
4927 new_val++;
4928 break;
4929 case CSINV_w:
4930 case CSINV_x:
4931 new_val = ~new_val;
4932 break;
4933 case CSNEG_w:
4934 case CSNEG_x:
4935 new_val = -new_val;
4936 break;
4937 default:
4938 VIXL_UNIMPLEMENTED();
4939 }
4940 }
4941 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4942 WriteRegister(reg_size, instr->GetRd(), new_val);
4943}
4944
4945
Jacob Bramleyca789742018-09-13 14:25:46 +01004946// clang-format off
4947#define PAUTH_MODES(V) \
4948 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
4949 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
4950 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
4951 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
4952 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
4953 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
4954 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
4955 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
4956// clang-format on
4957
Alexandre Ramesd3832962016-07-04 15:03:43 +01004958void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
4959 unsigned dst = instr->GetRd();
4960 unsigned src = instr->GetRn();
4961
4962 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004963#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
4964 case PAC##SUFFIX: { \
4965 uint64_t ptr = ReadXRegister(dst); \
4966 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
4967 break; \
4968 } \
4969 case AUT##SUFFIX: { \
4970 uint64_t ptr = ReadXRegister(dst); \
4971 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
4972 break; \
4973 }
4974
4975 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
4976#undef DEFINE_PAUTH_FUNCS
4977
4978 case XPACI:
4979 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
4980 break;
4981 case XPACD:
4982 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
4983 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004984 case RBIT_w:
4985 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
4986 break;
4987 case RBIT_x:
4988 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
4989 break;
4990 case REV16_w:
4991 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
4992 break;
4993 case REV16_x:
4994 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
4995 break;
4996 case REV_w:
4997 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
4998 break;
4999 case REV32_x:
5000 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5001 break;
5002 case REV_x:
5003 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5004 break;
5005 case CLZ_w:
5006 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5007 break;
5008 case CLZ_x:
5009 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5010 break;
5011 case CLS_w:
5012 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5013 break;
5014 case CLS_x:
5015 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5016 break;
5017 default:
5018 VIXL_UNIMPLEMENTED();
5019 }
5020}
5021
5022
5023uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5024 VIXL_ASSERT((n > 32) && (n <= 64));
5025 for (unsigned i = (n - 1); i >= 32; i--) {
5026 if (((data >> i) & 1) != 0) {
5027 uint64_t polysh32 = (uint64_t)poly << (i - 32);
5028 uint64_t mask = (UINT64_C(1) << i) - 1;
5029 data = ((data & mask) ^ polysh32);
5030 }
5031 }
5032 return data & 0xffffffff;
5033}
5034
5035
5036template <typename T>
5037uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5038 unsigned size = sizeof(val) * 8; // Number of bits in type T.
5039 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5040 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5041 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5042 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5043}
5044
5045
5046uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5047 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5048 // the CRC of each 32-bit word sequentially.
5049 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5050 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5051}
5052
5053
5054void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5055 Shift shift_op = NO_SHIFT;
5056 int64_t result = 0;
5057 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5058
5059 switch (instr->Mask(DataProcessing2SourceMask)) {
5060 case SDIV_w: {
5061 int32_t rn = ReadWRegister(instr->GetRn());
5062 int32_t rm = ReadWRegister(instr->GetRm());
5063 if ((rn == kWMinInt) && (rm == -1)) {
5064 result = kWMinInt;
5065 } else if (rm == 0) {
5066 // Division by zero can be trapped, but not on A-class processors.
5067 result = 0;
5068 } else {
5069 result = rn / rm;
5070 }
5071 break;
5072 }
5073 case SDIV_x: {
5074 int64_t rn = ReadXRegister(instr->GetRn());
5075 int64_t rm = ReadXRegister(instr->GetRm());
5076 if ((rn == kXMinInt) && (rm == -1)) {
5077 result = kXMinInt;
5078 } else if (rm == 0) {
5079 // Division by zero can be trapped, but not on A-class processors.
5080 result = 0;
5081 } else {
5082 result = rn / rm;
5083 }
5084 break;
5085 }
5086 case UDIV_w: {
5087 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5088 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5089 if (rm == 0) {
5090 // Division by zero can be trapped, but not on A-class processors.
5091 result = 0;
5092 } else {
5093 result = rn / rm;
5094 }
5095 break;
5096 }
5097 case UDIV_x: {
5098 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5099 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5100 if (rm == 0) {
5101 // Division by zero can be trapped, but not on A-class processors.
5102 result = 0;
5103 } else {
5104 result = rn / rm;
5105 }
5106 break;
5107 }
5108 case LSLV_w:
5109 case LSLV_x:
5110 shift_op = LSL;
5111 break;
5112 case LSRV_w:
5113 case LSRV_x:
5114 shift_op = LSR;
5115 break;
5116 case ASRV_w:
5117 case ASRV_x:
5118 shift_op = ASR;
5119 break;
5120 case RORV_w:
5121 case RORV_x:
5122 shift_op = ROR;
5123 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005124 case PACGA: {
5125 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5126 uint64_t src = static_cast<uint64_t>(
5127 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5128 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5129 result = code & 0xffffffff00000000;
5130 break;
5131 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005132 case CRC32B: {
5133 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5134 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5135 result = Crc32Checksum(acc, val, CRC32_POLY);
5136 break;
5137 }
5138 case CRC32H: {
5139 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5140 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5141 result = Crc32Checksum(acc, val, CRC32_POLY);
5142 break;
5143 }
5144 case CRC32W: {
5145 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5146 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5147 result = Crc32Checksum(acc, val, CRC32_POLY);
5148 break;
5149 }
5150 case CRC32X: {
5151 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5152 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5153 result = Crc32Checksum(acc, val, CRC32_POLY);
5154 reg_size = kWRegSize;
5155 break;
5156 }
5157 case CRC32CB: {
5158 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5159 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5160 result = Crc32Checksum(acc, val, CRC32C_POLY);
5161 break;
5162 }
5163 case CRC32CH: {
5164 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5165 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5166 result = Crc32Checksum(acc, val, CRC32C_POLY);
5167 break;
5168 }
5169 case CRC32CW: {
5170 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5171 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5172 result = Crc32Checksum(acc, val, CRC32C_POLY);
5173 break;
5174 }
5175 case CRC32CX: {
5176 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5177 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5178 result = Crc32Checksum(acc, val, CRC32C_POLY);
5179 reg_size = kWRegSize;
5180 break;
5181 }
5182 default:
5183 VIXL_UNIMPLEMENTED();
5184 }
5185
5186 if (shift_op != NO_SHIFT) {
5187 // Shift distance encoded in the least-significant five/six bits of the
5188 // register.
5189 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5190 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5191 result = ShiftOperand(reg_size,
5192 ReadRegister(reg_size, instr->GetRn()),
5193 shift_op,
5194 shift);
5195 }
5196 WriteRegister(reg_size, instr->GetRd(), result);
5197}
5198
5199
Alexandre Ramesd3832962016-07-04 15:03:43 +01005200void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5201 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5202
5203 uint64_t result = 0;
5204 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5205 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5206 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5207 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5208 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005209 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5210 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005211 switch (instr->Mask(DataProcessing3SourceMask)) {
5212 case MADD_w:
5213 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005214 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005215 break;
5216 case MSUB_w:
5217 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005218 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005219 break;
5220 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005221 result = ReadXRegister(instr->GetRa()) +
5222 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005223 break;
5224 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005225 result = ReadXRegister(instr->GetRa()) -
5226 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005227 break;
5228 case UMADDL_x:
5229 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5230 break;
5231 case UMSUBL_x:
5232 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5233 break;
5234 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005235 result =
5236 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5237 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005238 break;
5239 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005240 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5241 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005242 break;
5243 default:
5244 VIXL_UNIMPLEMENTED();
5245 }
5246 WriteRegister(reg_size, instr->GetRd(), result);
5247}
5248
5249
5250void Simulator::VisitBitfield(const Instruction* instr) {
5251 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5252 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005253 int R = instr->GetImmR();
5254 int S = instr->GetImmS();
5255 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005256 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005257 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005258 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005259 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005260 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005261 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005262 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005263 diff += reg_size;
5264 }
5265
5266 // inzero indicates if the extracted bitfield is inserted into the
5267 // destination register value or in zero.
5268 // If extend is true, extend the sign of the extracted bitfield.
5269 bool inzero = false;
5270 bool extend = false;
5271 switch (instr->Mask(BitfieldMask)) {
5272 case BFM_x:
5273 case BFM_w:
5274 break;
5275 case SBFM_x:
5276 case SBFM_w:
5277 inzero = true;
5278 extend = true;
5279 break;
5280 case UBFM_x:
5281 case UBFM_w:
5282 inzero = true;
5283 break;
5284 default:
5285 VIXL_UNIMPLEMENTED();
5286 }
5287
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005288 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5289 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005290 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005291 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005292 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005293 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5294 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005295
5296 // Merge sign extension, dest/zero and bitfield.
5297 result = signbits | (result & mask) | (dst & ~mask);
5298
5299 WriteRegister(reg_size, instr->GetRd(), result);
5300}
5301
5302
5303void Simulator::VisitExtract(const Instruction* instr) {
5304 unsigned lsb = instr->GetImmS();
5305 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5306 uint64_t low_res =
5307 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00005308 uint64_t high_res = (lsb == 0)
5309 ? 0
5310 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5311 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005312 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5313}
5314
5315
5316void Simulator::VisitFPImmediate(const Instruction* instr) {
5317 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005318 unsigned dest = instr->GetRd();
5319 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005320 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01005321 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01005322 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005323 case FMOV_s_imm:
5324 WriteSRegister(dest, instr->GetImmFP32());
5325 break;
5326 case FMOV_d_imm:
5327 WriteDRegister(dest, instr->GetImmFP64());
5328 break;
5329 default:
5330 VIXL_UNREACHABLE();
5331 }
5332}
5333
5334
5335void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5336 AssertSupportedFPCR();
5337
5338 unsigned dst = instr->GetRd();
5339 unsigned src = instr->GetRn();
5340
5341 FPRounding round = ReadRMode();
5342
5343 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005344 case FCVTAS_wh:
5345 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5346 break;
5347 case FCVTAS_xh:
5348 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5349 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005350 case FCVTAS_ws:
5351 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5352 break;
5353 case FCVTAS_xs:
5354 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5355 break;
5356 case FCVTAS_wd:
5357 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5358 break;
5359 case FCVTAS_xd:
5360 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5361 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005362 case FCVTAU_wh:
5363 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5364 break;
5365 case FCVTAU_xh:
5366 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5367 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005368 case FCVTAU_ws:
5369 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5370 break;
5371 case FCVTAU_xs:
5372 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5373 break;
5374 case FCVTAU_wd:
5375 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5376 break;
5377 case FCVTAU_xd:
5378 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5379 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005380 case FCVTMS_wh:
5381 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5382 break;
5383 case FCVTMS_xh:
5384 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5385 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005386 case FCVTMS_ws:
5387 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5388 break;
5389 case FCVTMS_xs:
5390 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5391 break;
5392 case FCVTMS_wd:
5393 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5394 break;
5395 case FCVTMS_xd:
5396 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5397 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005398 case FCVTMU_wh:
5399 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5400 break;
5401 case FCVTMU_xh:
5402 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5403 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005404 case FCVTMU_ws:
5405 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5406 break;
5407 case FCVTMU_xs:
5408 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5409 break;
5410 case FCVTMU_wd:
5411 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5412 break;
5413 case FCVTMU_xd:
5414 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5415 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005416 case FCVTPS_wh:
5417 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5418 break;
5419 case FCVTPS_xh:
5420 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5421 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005422 case FCVTPS_ws:
5423 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5424 break;
5425 case FCVTPS_xs:
5426 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5427 break;
5428 case FCVTPS_wd:
5429 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5430 break;
5431 case FCVTPS_xd:
5432 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5433 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005434 case FCVTPU_wh:
5435 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5436 break;
5437 case FCVTPU_xh:
5438 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5439 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005440 case FCVTPU_ws:
5441 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5442 break;
5443 case FCVTPU_xs:
5444 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5445 break;
5446 case FCVTPU_wd:
5447 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5448 break;
5449 case FCVTPU_xd:
5450 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5451 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005452 case FCVTNS_wh:
5453 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5454 break;
5455 case FCVTNS_xh:
5456 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5457 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005458 case FCVTNS_ws:
5459 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5460 break;
5461 case FCVTNS_xs:
5462 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5463 break;
5464 case FCVTNS_wd:
5465 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5466 break;
5467 case FCVTNS_xd:
5468 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5469 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005470 case FCVTNU_wh:
5471 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5472 break;
5473 case FCVTNU_xh:
5474 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5475 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005476 case FCVTNU_ws:
5477 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5478 break;
5479 case FCVTNU_xs:
5480 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5481 break;
5482 case FCVTNU_wd:
5483 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5484 break;
5485 case FCVTNU_xd:
5486 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5487 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005488 case FCVTZS_wh:
5489 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5490 break;
5491 case FCVTZS_xh:
5492 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5493 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005494 case FCVTZS_ws:
5495 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5496 break;
5497 case FCVTZS_xs:
5498 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5499 break;
5500 case FCVTZS_wd:
5501 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5502 break;
5503 case FCVTZS_xd:
5504 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5505 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005506 case FCVTZU_wh:
5507 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5508 break;
5509 case FCVTZU_xh:
5510 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5511 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005512 case FCVTZU_ws:
5513 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5514 break;
5515 case FCVTZU_xs:
5516 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5517 break;
5518 case FCVTZU_wd:
5519 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5520 break;
5521 case FCVTZU_xd:
5522 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5523 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005524 case FJCVTZS:
5525 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5526 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005527 case FMOV_hw:
5528 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5529 break;
5530 case FMOV_wh:
5531 WriteWRegister(dst, ReadHRegisterBits(src));
5532 break;
5533 case FMOV_xh:
5534 WriteXRegister(dst, ReadHRegisterBits(src));
5535 break;
5536 case FMOV_hx:
5537 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5538 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005539 case FMOV_ws:
5540 WriteWRegister(dst, ReadSRegisterBits(src));
5541 break;
5542 case FMOV_xd:
5543 WriteXRegister(dst, ReadDRegisterBits(src));
5544 break;
5545 case FMOV_sw:
5546 WriteSRegisterBits(dst, ReadWRegister(src));
5547 break;
5548 case FMOV_dx:
5549 WriteDRegisterBits(dst, ReadXRegister(src));
5550 break;
5551 case FMOV_d1_x:
5552 LogicVRegister(ReadVRegister(dst))
5553 .SetUint(kFormatD, 1, ReadXRegister(src));
5554 break;
5555 case FMOV_x_d1:
5556 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5557 break;
5558
5559 // A 32-bit input can be handled in the same way as a 64-bit input, since
5560 // the sign- or zero-extension will not affect the conversion.
5561 case SCVTF_dx:
5562 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5563 break;
5564 case SCVTF_dw:
5565 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5566 break;
5567 case UCVTF_dx:
5568 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5569 break;
5570 case UCVTF_dw: {
5571 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005572 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005573 break;
5574 }
5575 case SCVTF_sx:
5576 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5577 break;
5578 case SCVTF_sw:
5579 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5580 break;
5581 case UCVTF_sx:
5582 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5583 break;
5584 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01005585 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5586 break;
5587 }
5588 case SCVTF_hx:
5589 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5590 break;
5591 case SCVTF_hw:
5592 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5593 break;
5594 case UCVTF_hx:
5595 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5596 break;
5597 case UCVTF_hw: {
5598 WriteHRegister(dst,
5599 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005600 break;
5601 }
5602
5603 default:
5604 VIXL_UNREACHABLE();
5605 }
5606}
5607
5608
5609void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5610 AssertSupportedFPCR();
5611
5612 unsigned dst = instr->GetRd();
5613 unsigned src = instr->GetRn();
5614 int fbits = 64 - instr->GetFPScale();
5615
5616 FPRounding round = ReadRMode();
5617
5618 switch (instr->Mask(FPFixedPointConvertMask)) {
5619 // A 32-bit input can be handled in the same way as a 64-bit input, since
5620 // the sign- or zero-extension will not affect the conversion.
5621 case SCVTF_dx_fixed:
5622 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5623 break;
5624 case SCVTF_dw_fixed:
5625 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5626 break;
5627 case UCVTF_dx_fixed:
5628 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5629 break;
5630 case UCVTF_dw_fixed: {
5631 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005632 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005633 break;
5634 }
5635 case SCVTF_sx_fixed:
5636 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5637 break;
5638 case SCVTF_sw_fixed:
5639 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5640 break;
5641 case UCVTF_sx_fixed:
5642 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5643 break;
5644 case UCVTF_sw_fixed: {
5645 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005646 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5647 break;
5648 }
5649 case SCVTF_hx_fixed:
5650 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5651 break;
5652 case SCVTF_hw_fixed:
5653 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5654 break;
5655 case UCVTF_hx_fixed:
5656 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5657 break;
5658 case UCVTF_hw_fixed: {
5659 WriteHRegister(dst,
5660 UFixedToFloat16(ReadRegister<uint32_t>(src),
5661 fbits,
5662 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005663 break;
5664 }
5665 case FCVTZS_xd_fixed:
5666 WriteXRegister(dst,
5667 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5668 FPZero));
5669 break;
5670 case FCVTZS_wd_fixed:
5671 WriteWRegister(dst,
5672 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5673 FPZero));
5674 break;
5675 case FCVTZU_xd_fixed:
5676 WriteXRegister(dst,
5677 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5678 FPZero));
5679 break;
5680 case FCVTZU_wd_fixed:
5681 WriteWRegister(dst,
5682 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5683 FPZero));
5684 break;
5685 case FCVTZS_xs_fixed:
5686 WriteXRegister(dst,
5687 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5688 FPZero));
5689 break;
5690 case FCVTZS_ws_fixed:
5691 WriteWRegister(dst,
5692 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5693 FPZero));
5694 break;
5695 case FCVTZU_xs_fixed:
5696 WriteXRegister(dst,
5697 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5698 FPZero));
5699 break;
5700 case FCVTZU_ws_fixed:
5701 WriteWRegister(dst,
5702 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5703 FPZero));
5704 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005705 case FCVTZS_xh_fixed: {
5706 double output =
5707 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5708 WriteXRegister(dst, FPToInt64(output, FPZero));
5709 break;
5710 }
5711 case FCVTZS_wh_fixed: {
5712 double output =
5713 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5714 WriteWRegister(dst, FPToInt32(output, FPZero));
5715 break;
5716 }
5717 case FCVTZU_xh_fixed: {
5718 double output =
5719 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5720 WriteXRegister(dst, FPToUInt64(output, FPZero));
5721 break;
5722 }
5723 case FCVTZU_wh_fixed: {
5724 double output =
5725 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5726 WriteWRegister(dst, FPToUInt32(output, FPZero));
5727 break;
5728 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005729 default:
5730 VIXL_UNREACHABLE();
5731 }
5732}
5733
5734
5735void Simulator::VisitFPCompare(const Instruction* instr) {
5736 AssertSupportedFPCR();
5737
5738 FPTrapFlags trap = DisableTrap;
5739 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005740 case FCMPE_h:
5741 trap = EnableTrap;
5742 VIXL_FALLTHROUGH();
5743 case FCMP_h:
5744 FPCompare(ReadHRegister(instr->GetRn()),
5745 ReadHRegister(instr->GetRm()),
5746 trap);
5747 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005748 case FCMPE_s:
5749 trap = EnableTrap;
5750 VIXL_FALLTHROUGH();
5751 case FCMP_s:
5752 FPCompare(ReadSRegister(instr->GetRn()),
5753 ReadSRegister(instr->GetRm()),
5754 trap);
5755 break;
5756 case FCMPE_d:
5757 trap = EnableTrap;
5758 VIXL_FALLTHROUGH();
5759 case FCMP_d:
5760 FPCompare(ReadDRegister(instr->GetRn()),
5761 ReadDRegister(instr->GetRm()),
5762 trap);
5763 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005764 case FCMPE_h_zero:
5765 trap = EnableTrap;
5766 VIXL_FALLTHROUGH();
5767 case FCMP_h_zero:
5768 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5769 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005770 case FCMPE_s_zero:
5771 trap = EnableTrap;
5772 VIXL_FALLTHROUGH();
5773 case FCMP_s_zero:
5774 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
5775 break;
5776 case FCMPE_d_zero:
5777 trap = EnableTrap;
5778 VIXL_FALLTHROUGH();
5779 case FCMP_d_zero:
5780 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
5781 break;
5782 default:
5783 VIXL_UNIMPLEMENTED();
5784 }
5785}
5786
5787
5788void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
5789 AssertSupportedFPCR();
5790
5791 FPTrapFlags trap = DisableTrap;
5792 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005793 case FCCMPE_h:
5794 trap = EnableTrap;
5795 VIXL_FALLTHROUGH();
5796 case FCCMP_h:
5797 if (ConditionPassed(instr->GetCondition())) {
5798 FPCompare(ReadHRegister(instr->GetRn()),
5799 ReadHRegister(instr->GetRm()),
5800 trap);
5801 } else {
5802 ReadNzcv().SetFlags(instr->GetNzcv());
5803 LogSystemRegister(NZCV);
5804 }
5805 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005806 case FCCMPE_s:
5807 trap = EnableTrap;
5808 VIXL_FALLTHROUGH();
5809 case FCCMP_s:
5810 if (ConditionPassed(instr->GetCondition())) {
5811 FPCompare(ReadSRegister(instr->GetRn()),
5812 ReadSRegister(instr->GetRm()),
5813 trap);
5814 } else {
5815 ReadNzcv().SetFlags(instr->GetNzcv());
5816 LogSystemRegister(NZCV);
5817 }
5818 break;
5819 case FCCMPE_d:
5820 trap = EnableTrap;
5821 VIXL_FALLTHROUGH();
5822 case FCCMP_d:
5823 if (ConditionPassed(instr->GetCondition())) {
5824 FPCompare(ReadDRegister(instr->GetRn()),
5825 ReadDRegister(instr->GetRm()),
5826 trap);
5827 } else {
5828 ReadNzcv().SetFlags(instr->GetNzcv());
5829 LogSystemRegister(NZCV);
5830 }
5831 break;
5832 default:
5833 VIXL_UNIMPLEMENTED();
5834 }
5835}
5836
5837
5838void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
5839 AssertSupportedFPCR();
5840
5841 Instr selected;
5842 if (ConditionPassed(instr->GetCondition())) {
5843 selected = instr->GetRn();
5844 } else {
5845 selected = instr->GetRm();
5846 }
5847
5848 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005849 case FCSEL_h:
5850 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
5851 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005852 case FCSEL_s:
5853 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
5854 break;
5855 case FCSEL_d:
5856 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
5857 break;
5858 default:
5859 VIXL_UNIMPLEMENTED();
5860 }
5861}
5862
5863
5864void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
5865 AssertSupportedFPCR();
5866
5867 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01005868 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01005869 switch (instr->Mask(FPTypeMask)) {
5870 default:
5871 VIXL_UNREACHABLE_OR_FALLTHROUGH();
5872 case FP64:
5873 vform = kFormatD;
5874 break;
5875 case FP32:
5876 vform = kFormatS;
5877 break;
5878 case FP16:
5879 vform = kFormatH;
5880 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005881 }
Jacob Bramleyca789742018-09-13 14:25:46 +01005882
Alexandre Ramesd3832962016-07-04 15:03:43 +01005883 SimVRegister& rd = ReadVRegister(instr->GetRd());
5884 SimVRegister& rn = ReadVRegister(instr->GetRn());
5885 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07005886 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005887
5888 unsigned fd = instr->GetRd();
5889 unsigned fn = instr->GetRn();
5890
5891 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005892 case FMOV_h:
5893 WriteHRegister(fd, ReadHRegister(fn));
5894 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005895 case FMOV_s:
5896 WriteSRegister(fd, ReadSRegister(fn));
5897 return;
5898 case FMOV_d:
5899 WriteDRegister(fd, ReadDRegister(fn));
5900 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01005901 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005902 case FABS_s:
5903 case FABS_d:
5904 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
5905 // Explicitly log the register update whilst we have type information.
5906 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
5907 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01005908 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005909 case FNEG_s:
5910 case FNEG_d:
5911 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
5912 // Explicitly log the register update whilst we have type information.
5913 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
5914 return;
5915 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01005916 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005917 return;
5918 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01005919 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005920 return;
5921 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01005922 WriteHRegister(fd,
5923 Float16ToRawbits(
5924 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005925 return;
5926 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01005927 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005928 return;
5929 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01005930 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005931 return;
5932 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01005933 WriteHRegister(fd,
5934 Float16ToRawbits(
5935 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005936 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01005937 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005938 case FSQRT_s:
5939 case FSQRT_d:
5940 fsqrt(vform, rd, rn);
5941 // Explicitly log the register update whilst we have type information.
5942 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
5943 return;
TatWai Chong04471812019-03-19 14:29:00 -07005944 case FRINT32X_s:
5945 case FRINT32X_d:
5946 inexact_exception = true;
5947 frint_mode = kFrintToInt32;
5948 break; // Use FPCR rounding mode.
5949 case FRINT64X_s:
5950 case FRINT64X_d:
5951 inexact_exception = true;
5952 frint_mode = kFrintToInt64;
5953 break; // Use FPCR rounding mode.
5954 case FRINT32Z_s:
5955 case FRINT32Z_d:
5956 inexact_exception = true;
5957 frint_mode = kFrintToInt32;
5958 fpcr_rounding = FPZero;
5959 break;
5960 case FRINT64Z_s:
5961 case FRINT64Z_d:
5962 inexact_exception = true;
5963 frint_mode = kFrintToInt64;
5964 fpcr_rounding = FPZero;
5965 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005966 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005967 case FRINTI_s:
5968 case FRINTI_d:
5969 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01005970 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005971 case FRINTX_s:
5972 case FRINTX_d:
5973 inexact_exception = true;
5974 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005975 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005976 case FRINTA_s:
5977 case FRINTA_d:
5978 fpcr_rounding = FPTieAway;
5979 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005980 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005981 case FRINTM_s:
5982 case FRINTM_d:
5983 fpcr_rounding = FPNegativeInfinity;
5984 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005985 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005986 case FRINTN_s:
5987 case FRINTN_d:
5988 fpcr_rounding = FPTieEven;
5989 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005990 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005991 case FRINTP_s:
5992 case FRINTP_d:
5993 fpcr_rounding = FPPositiveInfinity;
5994 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005995 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01005996 case FRINTZ_s:
5997 case FRINTZ_d:
5998 fpcr_rounding = FPZero;
5999 break;
6000 default:
6001 VIXL_UNIMPLEMENTED();
6002 }
6003
6004 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006005 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006006 // Explicitly log the register update whilst we have type information.
6007 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6008}
6009
6010
6011void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6012 AssertSupportedFPCR();
6013
Carey Williamsd8bb3572018-04-10 11:58:07 +01006014 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006015 switch (instr->Mask(FPTypeMask)) {
6016 default:
6017 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6018 case FP64:
6019 vform = kFormatD;
6020 break;
6021 case FP32:
6022 vform = kFormatS;
6023 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006024 case FP16:
6025 vform = kFormatH;
6026 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006027 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006028 SimVRegister& rd = ReadVRegister(instr->GetRd());
6029 SimVRegister& rn = ReadVRegister(instr->GetRn());
6030 SimVRegister& rm = ReadVRegister(instr->GetRm());
6031
6032 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006033 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006034 case FADD_s:
6035 case FADD_d:
6036 fadd(vform, rd, rn, rm);
6037 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006038 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006039 case FSUB_s:
6040 case FSUB_d:
6041 fsub(vform, rd, rn, rm);
6042 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006043 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006044 case FMUL_s:
6045 case FMUL_d:
6046 fmul(vform, rd, rn, rm);
6047 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006048 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006049 case FNMUL_s:
6050 case FNMUL_d:
6051 fnmul(vform, rd, rn, rm);
6052 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006053 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006054 case FDIV_s:
6055 case FDIV_d:
6056 fdiv(vform, rd, rn, rm);
6057 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006058 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006059 case FMAX_s:
6060 case FMAX_d:
6061 fmax(vform, rd, rn, rm);
6062 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006063 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006064 case FMIN_s:
6065 case FMIN_d:
6066 fmin(vform, rd, rn, rm);
6067 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006068 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006069 case FMAXNM_s:
6070 case FMAXNM_d:
6071 fmaxnm(vform, rd, rn, rm);
6072 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006073 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006074 case FMINNM_s:
6075 case FMINNM_d:
6076 fminnm(vform, rd, rn, rm);
6077 break;
6078 default:
6079 VIXL_UNREACHABLE();
6080 }
6081 // Explicitly log the register update whilst we have type information.
6082 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6083}
6084
6085
6086void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6087 AssertSupportedFPCR();
6088
6089 unsigned fd = instr->GetRd();
6090 unsigned fn = instr->GetRn();
6091 unsigned fm = instr->GetRm();
6092 unsigned fa = instr->GetRa();
6093
6094 switch (instr->Mask(FPDataProcessing3SourceMask)) {
6095 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01006096 case FMADD_h:
6097 WriteHRegister(fd,
6098 FPMulAdd(ReadHRegister(fa),
6099 ReadHRegister(fn),
6100 ReadHRegister(fm)));
6101 break;
6102 case FMSUB_h:
6103 WriteHRegister(fd,
6104 FPMulAdd(ReadHRegister(fa),
6105 -ReadHRegister(fn),
6106 ReadHRegister(fm)));
6107 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006108 case FMADD_s:
6109 WriteSRegister(fd,
6110 FPMulAdd(ReadSRegister(fa),
6111 ReadSRegister(fn),
6112 ReadSRegister(fm)));
6113 break;
6114 case FMSUB_s:
6115 WriteSRegister(fd,
6116 FPMulAdd(ReadSRegister(fa),
6117 -ReadSRegister(fn),
6118 ReadSRegister(fm)));
6119 break;
6120 case FMADD_d:
6121 WriteDRegister(fd,
6122 FPMulAdd(ReadDRegister(fa),
6123 ReadDRegister(fn),
6124 ReadDRegister(fm)));
6125 break;
6126 case FMSUB_d:
6127 WriteDRegister(fd,
6128 FPMulAdd(ReadDRegister(fa),
6129 -ReadDRegister(fn),
6130 ReadDRegister(fm)));
6131 break;
6132 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01006133 case FNMADD_h:
6134 WriteHRegister(fd,
6135 FPMulAdd(-ReadHRegister(fa),
6136 -ReadHRegister(fn),
6137 ReadHRegister(fm)));
6138 break;
6139 case FNMSUB_h:
6140 WriteHRegister(fd,
6141 FPMulAdd(-ReadHRegister(fa),
6142 ReadHRegister(fn),
6143 ReadHRegister(fm)));
6144 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006145 case FNMADD_s:
6146 WriteSRegister(fd,
6147 FPMulAdd(-ReadSRegister(fa),
6148 -ReadSRegister(fn),
6149 ReadSRegister(fm)));
6150 break;
6151 case FNMSUB_s:
6152 WriteSRegister(fd,
6153 FPMulAdd(-ReadSRegister(fa),
6154 ReadSRegister(fn),
6155 ReadSRegister(fm)));
6156 break;
6157 case FNMADD_d:
6158 WriteDRegister(fd,
6159 FPMulAdd(-ReadDRegister(fa),
6160 -ReadDRegister(fn),
6161 ReadDRegister(fm)));
6162 break;
6163 case FNMSUB_d:
6164 WriteDRegister(fd,
6165 FPMulAdd(-ReadDRegister(fa),
6166 ReadDRegister(fn),
6167 ReadDRegister(fm)));
6168 break;
6169 default:
6170 VIXL_UNIMPLEMENTED();
6171 }
6172}
6173
6174
6175bool Simulator::FPProcessNaNs(const Instruction* instr) {
6176 unsigned fd = instr->GetRd();
6177 unsigned fn = instr->GetRn();
6178 unsigned fm = instr->GetRm();
6179 bool done = false;
6180
6181 if (instr->Mask(FP64) == FP64) {
6182 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006183 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006184 WriteDRegister(fd, result);
6185 done = true;
6186 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006187 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006188 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006189 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006190 WriteSRegister(fd, result);
6191 done = true;
6192 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006193 } else {
6194 VIXL_ASSERT(instr->Mask(FP16) == FP16);
6195 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006196 }
6197
6198 return done;
6199}
6200
6201
6202void Simulator::SysOp_W(int op, int64_t val) {
6203 switch (op) {
6204 case IVAU:
6205 case CVAC:
6206 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01006207 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08006208 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006209 case CIVAC: {
6210 // Perform a dummy memory access to ensure that we have read access
6211 // to the specified address.
6212 volatile uint8_t y = Memory::Read<uint8_t>(val);
6213 USE(y);
6214 // TODO: Implement "case ZVA:".
6215 break;
6216 }
6217 default:
6218 VIXL_UNIMPLEMENTED();
6219 }
6220}
6221
6222
Jacob Bramleyca789742018-09-13 14:25:46 +01006223// clang-format off
6224#define PAUTH_SYSTEM_MODES(V) \
6225 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
6226 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
6227 V(AZ, 30, 0x00000000, kPACKeyIA) \
6228 V(BZ, 30, 0x00000000, kPACKeyIB) \
6229 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6230 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6231// clang-format on
6232
6233
Alexandre Ramesd3832962016-07-04 15:03:43 +01006234void Simulator::VisitSystem(const Instruction* instr) {
6235 // Some system instructions hijack their Op and Cp fields to represent a
6236 // range of immediates instead of indicating a different instruction. This
6237 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01006238 if (instr->GetInstructionBits() == XPACLRI) {
6239 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00006240 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6241 switch (instr->Mask(SystemPStateMask)) {
6242 case CFINV:
6243 ReadNzcv().SetC(!ReadC());
6244 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00006245 case AXFLAG:
6246 ReadNzcv().SetN(0);
6247 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6248 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6249 ReadNzcv().SetV(0);
6250 break;
6251 case XAFLAG: {
6252 // Can't set the flags in place due to the logical dependencies.
6253 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6254 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6255 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6256 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6257 ReadNzcv().SetN(n);
6258 ReadNzcv().SetZ(z);
6259 ReadNzcv().SetC(c);
6260 ReadNzcv().SetV(v);
6261 break;
6262 }
Alexander Gilday2487f142018-11-05 13:07:27 +00006263 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006264 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006265 // Check BType allows PACI[AB]SP instructions.
6266 if (PcIsInGuardedPage()) {
6267 Instr i = instr->Mask(SystemPAuthMask);
6268 if ((i == PACIASP) || (i == PACIBSP)) {
6269 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006270 case BranchFromGuardedNotToIP:
6271 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6272 // assume here to be zero. This allows execution of PACI[AB]SP when
6273 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00006274 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006275 case BranchFromUnguardedOrToIP:
6276 case BranchAndLink:
6277 break;
6278 }
6279 }
6280 }
6281
Jacob Bramleyca789742018-09-13 14:25:46 +01006282 switch (instr->Mask(SystemPAuthMask)) {
6283#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
6284 case PACI##SUFFIX: \
6285 WriteXRegister(DST, \
6286 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6287 break; \
6288 case AUTI##SUFFIX: \
6289 WriteXRegister(DST, \
6290 AuthPAC(ReadXRegister(DST), \
6291 MOD, \
6292 KEY, \
6293 kInstructionPointer)); \
6294 break;
6295
6296 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6297#undef DEFINE_PAUTH_FUNCS
6298 }
6299 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6300 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006301 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6302 switch (instr->Mask(SystemExclusiveMonitorMask)) {
6303 case CLREX: {
6304 PrintExclusiveAccessWarning();
6305 ClearLocalMonitor();
6306 break;
6307 }
6308 }
6309 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6310 switch (instr->Mask(SystemSysRegMask)) {
6311 case MRS: {
6312 switch (instr->GetImmSystemRegister()) {
6313 case NZCV:
6314 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6315 break;
6316 case FPCR:
6317 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6318 break;
TatWai Chong04edf682018-12-27 16:01:02 -08006319 case RNDR:
6320 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00006321 uint64_t high = jrand48(rand_state_);
6322 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08006323 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6324 WriteXRegister(instr->GetRt(), rand_num);
6325 // Simulate successful random number generation.
6326 // TODO: Return failure occasionally as a random number cannot be
6327 // returned in a period of time.
6328 ReadNzcv().SetRawValue(NoFlag);
6329 LogSystemRegister(NZCV);
6330 break;
6331 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006332 default:
6333 VIXL_UNIMPLEMENTED();
6334 }
6335 break;
6336 }
6337 case MSR: {
6338 switch (instr->GetImmSystemRegister()) {
6339 case NZCV:
6340 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6341 LogSystemRegister(NZCV);
6342 break;
6343 case FPCR:
6344 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6345 LogSystemRegister(FPCR);
6346 break;
6347 default:
6348 VIXL_UNIMPLEMENTED();
6349 }
6350 break;
6351 }
6352 }
6353 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6354 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6355 switch (instr->GetImmHint()) {
6356 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01006357 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00006358 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006359 case BTI_jc:
6360 break;
6361 case BTI:
6362 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6363 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6364 }
6365 break;
6366 case BTI_c:
6367 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6368 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6369 }
6370 break;
6371 case BTI_j:
6372 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6373 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6374 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006375 break;
6376 default:
6377 VIXL_UNIMPLEMENTED();
6378 }
6379 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6380 __sync_synchronize();
6381 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6382 switch (instr->Mask(SystemSysMask)) {
6383 case SYS:
6384 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6385 break;
6386 default:
6387 VIXL_UNIMPLEMENTED();
6388 }
6389 } else {
6390 VIXL_UNIMPLEMENTED();
6391 }
6392}
6393
6394
6395void Simulator::VisitException(const Instruction* instr) {
6396 switch (instr->Mask(ExceptionMask)) {
6397 case HLT:
6398 switch (instr->GetImmException()) {
6399 case kUnreachableOpcode:
6400 DoUnreachable(instr);
6401 return;
6402 case kTraceOpcode:
6403 DoTrace(instr);
6404 return;
6405 case kLogOpcode:
6406 DoLog(instr);
6407 return;
6408 case kPrintfOpcode:
6409 DoPrintf(instr);
6410 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01006411 case kRuntimeCallOpcode:
6412 DoRuntimeCall(instr);
6413 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01006414 case kSetCPUFeaturesOpcode:
6415 case kEnableCPUFeaturesOpcode:
6416 case kDisableCPUFeaturesOpcode:
6417 DoConfigureCPUFeatures(instr);
6418 return;
6419 case kSaveCPUFeaturesOpcode:
6420 DoSaveCPUFeatures(instr);
6421 return;
6422 case kRestoreCPUFeaturesOpcode:
6423 DoRestoreCPUFeatures(instr);
6424 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006425 default:
6426 HostBreakpoint();
6427 return;
6428 }
6429 case BRK:
6430 HostBreakpoint();
6431 return;
6432 default:
6433 VIXL_UNIMPLEMENTED();
6434 }
6435}
6436
6437
6438void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6439 VisitUnimplemented(instr);
6440}
6441
6442
6443void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6444 VisitUnimplemented(instr);
6445}
6446
6447
6448void Simulator::VisitCryptoAES(const Instruction* instr) {
6449 VisitUnimplemented(instr);
6450}
6451
6452
6453void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6454 NEONFormatDecoder nfd(instr);
6455 VectorFormat vf = nfd.GetVectorFormat();
6456
6457 static const NEONFormatMap map_lp =
6458 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6459 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6460
6461 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6462 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6463
6464 static const NEONFormatMap map_fcvtn = {{22, 30},
6465 {NF_4H, NF_8H, NF_2S, NF_4S}};
6466 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6467
6468 SimVRegister& rd = ReadVRegister(instr->GetRd());
6469 SimVRegister& rn = ReadVRegister(instr->GetRn());
6470
6471 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6472 // These instructions all use a two bit size field, except NOT and RBIT,
6473 // which use the field to encode the operation.
6474 switch (instr->Mask(NEON2RegMiscMask)) {
6475 case NEON_REV64:
6476 rev64(vf, rd, rn);
6477 break;
6478 case NEON_REV32:
6479 rev32(vf, rd, rn);
6480 break;
6481 case NEON_REV16:
6482 rev16(vf, rd, rn);
6483 break;
6484 case NEON_SUQADD:
6485 suqadd(vf, rd, rn);
6486 break;
6487 case NEON_USQADD:
6488 usqadd(vf, rd, rn);
6489 break;
6490 case NEON_CLS:
6491 cls(vf, rd, rn);
6492 break;
6493 case NEON_CLZ:
6494 clz(vf, rd, rn);
6495 break;
6496 case NEON_CNT:
6497 cnt(vf, rd, rn);
6498 break;
6499 case NEON_SQABS:
6500 abs(vf, rd, rn).SignedSaturate(vf);
6501 break;
6502 case NEON_SQNEG:
6503 neg(vf, rd, rn).SignedSaturate(vf);
6504 break;
6505 case NEON_CMGT_zero:
6506 cmp(vf, rd, rn, 0, gt);
6507 break;
6508 case NEON_CMGE_zero:
6509 cmp(vf, rd, rn, 0, ge);
6510 break;
6511 case NEON_CMEQ_zero:
6512 cmp(vf, rd, rn, 0, eq);
6513 break;
6514 case NEON_CMLE_zero:
6515 cmp(vf, rd, rn, 0, le);
6516 break;
6517 case NEON_CMLT_zero:
6518 cmp(vf, rd, rn, 0, lt);
6519 break;
6520 case NEON_ABS:
6521 abs(vf, rd, rn);
6522 break;
6523 case NEON_NEG:
6524 neg(vf, rd, rn);
6525 break;
6526 case NEON_SADDLP:
6527 saddlp(vf_lp, rd, rn);
6528 break;
6529 case NEON_UADDLP:
6530 uaddlp(vf_lp, rd, rn);
6531 break;
6532 case NEON_SADALP:
6533 sadalp(vf_lp, rd, rn);
6534 break;
6535 case NEON_UADALP:
6536 uadalp(vf_lp, rd, rn);
6537 break;
6538 case NEON_RBIT_NOT:
6539 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6540 switch (instr->GetFPType()) {
6541 case 0:
6542 not_(vf, rd, rn);
6543 break;
6544 case 1:
6545 rbit(vf, rd, rn);
6546 break;
6547 default:
6548 VIXL_UNIMPLEMENTED();
6549 }
6550 break;
6551 }
6552 } else {
6553 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6554 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6555 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006556 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006557
6558 // These instructions all use a one bit size field, except XTN, SQXTUN,
6559 // SHLL, SQXTN and UQXTN, which use a two bit size field.
6560 switch (instr->Mask(NEON2RegMiscFPMask)) {
6561 case NEON_FABS:
6562 fabs_(fpf, rd, rn);
6563 return;
6564 case NEON_FNEG:
6565 fneg(fpf, rd, rn);
6566 return;
6567 case NEON_FSQRT:
6568 fsqrt(fpf, rd, rn);
6569 return;
6570 case NEON_FCVTL:
6571 if (instr->Mask(NEON_Q)) {
6572 fcvtl2(vf_fcvtl, rd, rn);
6573 } else {
6574 fcvtl(vf_fcvtl, rd, rn);
6575 }
6576 return;
6577 case NEON_FCVTN:
6578 if (instr->Mask(NEON_Q)) {
6579 fcvtn2(vf_fcvtn, rd, rn);
6580 } else {
6581 fcvtn(vf_fcvtn, rd, rn);
6582 }
6583 return;
6584 case NEON_FCVTXN:
6585 if (instr->Mask(NEON_Q)) {
6586 fcvtxn2(vf_fcvtn, rd, rn);
6587 } else {
6588 fcvtxn(vf_fcvtn, rd, rn);
6589 }
6590 return;
6591
6592 // The following instructions break from the switch statement, rather
6593 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07006594 case NEON_FRINT32X:
6595 inexact_exception = true;
6596 frint_mode = kFrintToInt32;
6597 break; // Use FPCR rounding mode.
6598 case NEON_FRINT32Z:
6599 inexact_exception = true;
6600 frint_mode = kFrintToInt32;
6601 fpcr_rounding = FPZero;
6602 break;
6603 case NEON_FRINT64X:
6604 inexact_exception = true;
6605 frint_mode = kFrintToInt64;
6606 break; // Use FPCR rounding mode.
6607 case NEON_FRINT64Z:
6608 inexact_exception = true;
6609 frint_mode = kFrintToInt64;
6610 fpcr_rounding = FPZero;
6611 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006612 case NEON_FRINTI:
6613 break; // Use FPCR rounding mode.
6614 case NEON_FRINTX:
6615 inexact_exception = true;
6616 break;
6617 case NEON_FRINTA:
6618 fpcr_rounding = FPTieAway;
6619 break;
6620 case NEON_FRINTM:
6621 fpcr_rounding = FPNegativeInfinity;
6622 break;
6623 case NEON_FRINTN:
6624 fpcr_rounding = FPTieEven;
6625 break;
6626 case NEON_FRINTP:
6627 fpcr_rounding = FPPositiveInfinity;
6628 break;
6629 case NEON_FRINTZ:
6630 fpcr_rounding = FPZero;
6631 break;
6632
6633 case NEON_FCVTNS:
6634 fcvts(fpf, rd, rn, FPTieEven);
6635 return;
6636 case NEON_FCVTNU:
6637 fcvtu(fpf, rd, rn, FPTieEven);
6638 return;
6639 case NEON_FCVTPS:
6640 fcvts(fpf, rd, rn, FPPositiveInfinity);
6641 return;
6642 case NEON_FCVTPU:
6643 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6644 return;
6645 case NEON_FCVTMS:
6646 fcvts(fpf, rd, rn, FPNegativeInfinity);
6647 return;
6648 case NEON_FCVTMU:
6649 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6650 return;
6651 case NEON_FCVTZS:
6652 fcvts(fpf, rd, rn, FPZero);
6653 return;
6654 case NEON_FCVTZU:
6655 fcvtu(fpf, rd, rn, FPZero);
6656 return;
6657 case NEON_FCVTAS:
6658 fcvts(fpf, rd, rn, FPTieAway);
6659 return;
6660 case NEON_FCVTAU:
6661 fcvtu(fpf, rd, rn, FPTieAway);
6662 return;
6663 case NEON_SCVTF:
6664 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6665 return;
6666 case NEON_UCVTF:
6667 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6668 return;
6669 case NEON_URSQRTE:
6670 ursqrte(fpf, rd, rn);
6671 return;
6672 case NEON_URECPE:
6673 urecpe(fpf, rd, rn);
6674 return;
6675 case NEON_FRSQRTE:
6676 frsqrte(fpf, rd, rn);
6677 return;
6678 case NEON_FRECPE:
6679 frecpe(fpf, rd, rn, fpcr_rounding);
6680 return;
6681 case NEON_FCMGT_zero:
6682 fcmp_zero(fpf, rd, rn, gt);
6683 return;
6684 case NEON_FCMGE_zero:
6685 fcmp_zero(fpf, rd, rn, ge);
6686 return;
6687 case NEON_FCMEQ_zero:
6688 fcmp_zero(fpf, rd, rn, eq);
6689 return;
6690 case NEON_FCMLE_zero:
6691 fcmp_zero(fpf, rd, rn, le);
6692 return;
6693 case NEON_FCMLT_zero:
6694 fcmp_zero(fpf, rd, rn, lt);
6695 return;
6696 default:
6697 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6698 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6699 switch (instr->Mask(NEON2RegMiscMask)) {
6700 case NEON_XTN:
6701 xtn(vf, rd, rn);
6702 return;
6703 case NEON_SQXTN:
6704 sqxtn(vf, rd, rn);
6705 return;
6706 case NEON_UQXTN:
6707 uqxtn(vf, rd, rn);
6708 return;
6709 case NEON_SQXTUN:
6710 sqxtun(vf, rd, rn);
6711 return;
6712 case NEON_SHLL:
6713 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6714 if (instr->Mask(NEON_Q)) {
6715 shll2(vf, rd, rn);
6716 } else {
6717 shll(vf, rd, rn);
6718 }
6719 return;
6720 default:
6721 VIXL_UNIMPLEMENTED();
6722 }
6723 } else {
6724 VIXL_UNIMPLEMENTED();
6725 }
6726 }
6727
6728 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006729 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006730 }
6731}
6732
6733
Jacob Bramleyca789742018-09-13 14:25:46 +01006734void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6735 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6736 NEONFormatDecoder nfd(instr);
6737 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6738
6739 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6740
6741 SimVRegister& rd = ReadVRegister(instr->GetRd());
6742 SimVRegister& rn = ReadVRegister(instr->GetRn());
6743
6744 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6745 case NEON_SCVTF_H:
6746 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6747 return;
6748 case NEON_UCVTF_H:
6749 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6750 return;
6751 case NEON_FCVTNS_H:
6752 fcvts(fpf, rd, rn, FPTieEven);
6753 return;
6754 case NEON_FCVTNU_H:
6755 fcvtu(fpf, rd, rn, FPTieEven);
6756 return;
6757 case NEON_FCVTPS_H:
6758 fcvts(fpf, rd, rn, FPPositiveInfinity);
6759 return;
6760 case NEON_FCVTPU_H:
6761 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6762 return;
6763 case NEON_FCVTMS_H:
6764 fcvts(fpf, rd, rn, FPNegativeInfinity);
6765 return;
6766 case NEON_FCVTMU_H:
6767 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6768 return;
6769 case NEON_FCVTZS_H:
6770 fcvts(fpf, rd, rn, FPZero);
6771 return;
6772 case NEON_FCVTZU_H:
6773 fcvtu(fpf, rd, rn, FPZero);
6774 return;
6775 case NEON_FCVTAS_H:
6776 fcvts(fpf, rd, rn, FPTieAway);
6777 return;
6778 case NEON_FCVTAU_H:
6779 fcvtu(fpf, rd, rn, FPTieAway);
6780 return;
6781 case NEON_FRINTI_H:
6782 frint(fpf, rd, rn, fpcr_rounding, false);
6783 return;
6784 case NEON_FRINTX_H:
6785 frint(fpf, rd, rn, fpcr_rounding, true);
6786 return;
6787 case NEON_FRINTA_H:
6788 frint(fpf, rd, rn, FPTieAway, false);
6789 return;
6790 case NEON_FRINTM_H:
6791 frint(fpf, rd, rn, FPNegativeInfinity, false);
6792 return;
6793 case NEON_FRINTN_H:
6794 frint(fpf, rd, rn, FPTieEven, false);
6795 return;
6796 case NEON_FRINTP_H:
6797 frint(fpf, rd, rn, FPPositiveInfinity, false);
6798 return;
6799 case NEON_FRINTZ_H:
6800 frint(fpf, rd, rn, FPZero, false);
6801 return;
6802 case NEON_FABS_H:
6803 fabs_(fpf, rd, rn);
6804 return;
6805 case NEON_FNEG_H:
6806 fneg(fpf, rd, rn);
6807 return;
6808 case NEON_FSQRT_H:
6809 fsqrt(fpf, rd, rn);
6810 return;
6811 case NEON_FRSQRTE_H:
6812 frsqrte(fpf, rd, rn);
6813 return;
6814 case NEON_FRECPE_H:
6815 frecpe(fpf, rd, rn, fpcr_rounding);
6816 return;
6817 case NEON_FCMGT_H_zero:
6818 fcmp_zero(fpf, rd, rn, gt);
6819 return;
6820 case NEON_FCMGE_H_zero:
6821 fcmp_zero(fpf, rd, rn, ge);
6822 return;
6823 case NEON_FCMEQ_H_zero:
6824 fcmp_zero(fpf, rd, rn, eq);
6825 return;
6826 case NEON_FCMLE_H_zero:
6827 fcmp_zero(fpf, rd, rn, le);
6828 return;
6829 case NEON_FCMLT_H_zero:
6830 fcmp_zero(fpf, rd, rn, lt);
6831 return;
6832 default:
6833 VIXL_UNIMPLEMENTED();
6834 return;
6835 }
6836}
6837
6838
Alexandre Ramesd3832962016-07-04 15:03:43 +01006839void Simulator::VisitNEON3Same(const Instruction* instr) {
6840 NEONFormatDecoder nfd(instr);
6841 SimVRegister& rd = ReadVRegister(instr->GetRd());
6842 SimVRegister& rn = ReadVRegister(instr->GetRn());
6843 SimVRegister& rm = ReadVRegister(instr->GetRm());
6844
6845 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
6846 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6847 switch (instr->Mask(NEON3SameLogicalMask)) {
6848 case NEON_AND:
6849 and_(vf, rd, rn, rm);
6850 break;
6851 case NEON_ORR:
6852 orr(vf, rd, rn, rm);
6853 break;
6854 case NEON_ORN:
6855 orn(vf, rd, rn, rm);
6856 break;
6857 case NEON_EOR:
6858 eor(vf, rd, rn, rm);
6859 break;
6860 case NEON_BIC:
6861 bic(vf, rd, rn, rm);
6862 break;
6863 case NEON_BIF:
6864 bif(vf, rd, rn, rm);
6865 break;
6866 case NEON_BIT:
6867 bit(vf, rd, rn, rm);
6868 break;
6869 case NEON_BSL:
6870 bsl(vf, rd, rn, rm);
6871 break;
6872 default:
6873 VIXL_UNIMPLEMENTED();
6874 }
6875 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
6876 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
6877 switch (instr->Mask(NEON3SameFPMask)) {
6878 case NEON_FADD:
6879 fadd(vf, rd, rn, rm);
6880 break;
6881 case NEON_FSUB:
6882 fsub(vf, rd, rn, rm);
6883 break;
6884 case NEON_FMUL:
6885 fmul(vf, rd, rn, rm);
6886 break;
6887 case NEON_FDIV:
6888 fdiv(vf, rd, rn, rm);
6889 break;
6890 case NEON_FMAX:
6891 fmax(vf, rd, rn, rm);
6892 break;
6893 case NEON_FMIN:
6894 fmin(vf, rd, rn, rm);
6895 break;
6896 case NEON_FMAXNM:
6897 fmaxnm(vf, rd, rn, rm);
6898 break;
6899 case NEON_FMINNM:
6900 fminnm(vf, rd, rn, rm);
6901 break;
6902 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08006903 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006904 break;
6905 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08006906 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006907 break;
6908 case NEON_FMULX:
6909 fmulx(vf, rd, rn, rm);
6910 break;
6911 case NEON_FACGE:
6912 fabscmp(vf, rd, rn, rm, ge);
6913 break;
6914 case NEON_FACGT:
6915 fabscmp(vf, rd, rn, rm, gt);
6916 break;
6917 case NEON_FCMEQ:
6918 fcmp(vf, rd, rn, rm, eq);
6919 break;
6920 case NEON_FCMGE:
6921 fcmp(vf, rd, rn, rm, ge);
6922 break;
6923 case NEON_FCMGT:
6924 fcmp(vf, rd, rn, rm, gt);
6925 break;
6926 case NEON_FRECPS:
6927 frecps(vf, rd, rn, rm);
6928 break;
6929 case NEON_FRSQRTS:
6930 frsqrts(vf, rd, rn, rm);
6931 break;
6932 case NEON_FABD:
6933 fabd(vf, rd, rn, rm);
6934 break;
6935 case NEON_FADDP:
6936 faddp(vf, rd, rn, rm);
6937 break;
6938 case NEON_FMAXP:
6939 fmaxp(vf, rd, rn, rm);
6940 break;
6941 case NEON_FMAXNMP:
6942 fmaxnmp(vf, rd, rn, rm);
6943 break;
6944 case NEON_FMINP:
6945 fminp(vf, rd, rn, rm);
6946 break;
6947 case NEON_FMINNMP:
6948 fminnmp(vf, rd, rn, rm);
6949 break;
6950 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01006951 // FMLAL{2} and FMLSL{2} have special-case encodings.
6952 switch (instr->Mask(NEON3SameFHMMask)) {
6953 case NEON_FMLAL:
6954 fmlal(vf, rd, rn, rm);
6955 break;
6956 case NEON_FMLAL2:
6957 fmlal2(vf, rd, rn, rm);
6958 break;
6959 case NEON_FMLSL:
6960 fmlsl(vf, rd, rn, rm);
6961 break;
6962 case NEON_FMLSL2:
6963 fmlsl2(vf, rd, rn, rm);
6964 break;
6965 default:
6966 VIXL_UNIMPLEMENTED();
6967 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006968 }
6969 } else {
6970 VectorFormat vf = nfd.GetVectorFormat();
6971 switch (instr->Mask(NEON3SameMask)) {
6972 case NEON_ADD:
6973 add(vf, rd, rn, rm);
6974 break;
6975 case NEON_ADDP:
6976 addp(vf, rd, rn, rm);
6977 break;
6978 case NEON_CMEQ:
6979 cmp(vf, rd, rn, rm, eq);
6980 break;
6981 case NEON_CMGE:
6982 cmp(vf, rd, rn, rm, ge);
6983 break;
6984 case NEON_CMGT:
6985 cmp(vf, rd, rn, rm, gt);
6986 break;
6987 case NEON_CMHI:
6988 cmp(vf, rd, rn, rm, hi);
6989 break;
6990 case NEON_CMHS:
6991 cmp(vf, rd, rn, rm, hs);
6992 break;
6993 case NEON_CMTST:
6994 cmptst(vf, rd, rn, rm);
6995 break;
6996 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01006997 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006998 break;
6999 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01007000 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007001 break;
7002 case NEON_MUL:
7003 mul(vf, rd, rn, rm);
7004 break;
7005 case NEON_PMUL:
7006 pmul(vf, rd, rn, rm);
7007 break;
7008 case NEON_SMAX:
7009 smax(vf, rd, rn, rm);
7010 break;
7011 case NEON_SMAXP:
7012 smaxp(vf, rd, rn, rm);
7013 break;
7014 case NEON_SMIN:
7015 smin(vf, rd, rn, rm);
7016 break;
7017 case NEON_SMINP:
7018 sminp(vf, rd, rn, rm);
7019 break;
7020 case NEON_SUB:
7021 sub(vf, rd, rn, rm);
7022 break;
7023 case NEON_UMAX:
7024 umax(vf, rd, rn, rm);
7025 break;
7026 case NEON_UMAXP:
7027 umaxp(vf, rd, rn, rm);
7028 break;
7029 case NEON_UMIN:
7030 umin(vf, rd, rn, rm);
7031 break;
7032 case NEON_UMINP:
7033 uminp(vf, rd, rn, rm);
7034 break;
7035 case NEON_SSHL:
7036 sshl(vf, rd, rn, rm);
7037 break;
7038 case NEON_USHL:
7039 ushl(vf, rd, rn, rm);
7040 break;
7041 case NEON_SABD:
7042 absdiff(vf, rd, rn, rm, true);
7043 break;
7044 case NEON_UABD:
7045 absdiff(vf, rd, rn, rm, false);
7046 break;
7047 case NEON_SABA:
7048 saba(vf, rd, rn, rm);
7049 break;
7050 case NEON_UABA:
7051 uaba(vf, rd, rn, rm);
7052 break;
7053 case NEON_UQADD:
7054 add(vf, rd, rn, rm).UnsignedSaturate(vf);
7055 break;
7056 case NEON_SQADD:
7057 add(vf, rd, rn, rm).SignedSaturate(vf);
7058 break;
7059 case NEON_UQSUB:
7060 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7061 break;
7062 case NEON_SQSUB:
7063 sub(vf, rd, rn, rm).SignedSaturate(vf);
7064 break;
7065 case NEON_SQDMULH:
7066 sqdmulh(vf, rd, rn, rm);
7067 break;
7068 case NEON_SQRDMULH:
7069 sqrdmulh(vf, rd, rn, rm);
7070 break;
7071 case NEON_UQSHL:
7072 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7073 break;
7074 case NEON_SQSHL:
7075 sshl(vf, rd, rn, rm).SignedSaturate(vf);
7076 break;
7077 case NEON_URSHL:
7078 ushl(vf, rd, rn, rm).Round(vf);
7079 break;
7080 case NEON_SRSHL:
7081 sshl(vf, rd, rn, rm).Round(vf);
7082 break;
7083 case NEON_UQRSHL:
7084 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7085 break;
7086 case NEON_SQRSHL:
7087 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7088 break;
7089 case NEON_UHADD:
7090 add(vf, rd, rn, rm).Uhalve(vf);
7091 break;
7092 case NEON_URHADD:
7093 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7094 break;
7095 case NEON_SHADD:
7096 add(vf, rd, rn, rm).Halve(vf);
7097 break;
7098 case NEON_SRHADD:
7099 add(vf, rd, rn, rm).Halve(vf).Round(vf);
7100 break;
7101 case NEON_UHSUB:
7102 sub(vf, rd, rn, rm).Uhalve(vf);
7103 break;
7104 case NEON_SHSUB:
7105 sub(vf, rd, rn, rm).Halve(vf);
7106 break;
7107 default:
7108 VIXL_UNIMPLEMENTED();
7109 }
7110 }
7111}
7112
7113
Jacob Bramleyca789742018-09-13 14:25:46 +01007114void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7115 NEONFormatDecoder nfd(instr);
7116 SimVRegister& rd = ReadVRegister(instr->GetRd());
7117 SimVRegister& rn = ReadVRegister(instr->GetRn());
7118 SimVRegister& rm = ReadVRegister(instr->GetRm());
7119
7120 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7121 switch (instr->Mask(NEON3SameFP16Mask)) {
7122#define SIM_FUNC(A, B) \
7123 case NEON_##A##_H: \
7124 B(vf, rd, rn, rm); \
7125 break;
7126 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007127 SIM_FUNC(FADD, fadd);
7128 SIM_FUNC(FMULX, fmulx);
7129 SIM_FUNC(FMAX, fmax);
7130 SIM_FUNC(FRECPS, frecps);
7131 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007132 SIM_FUNC(FSUB, fsub);
7133 SIM_FUNC(FMIN, fmin);
7134 SIM_FUNC(FRSQRTS, frsqrts);
7135 SIM_FUNC(FMAXNMP, fmaxnmp);
7136 SIM_FUNC(FADDP, faddp);
7137 SIM_FUNC(FMUL, fmul);
7138 SIM_FUNC(FMAXP, fmaxp);
7139 SIM_FUNC(FDIV, fdiv);
7140 SIM_FUNC(FMINNMP, fminnmp);
7141 SIM_FUNC(FABD, fabd);
7142 SIM_FUNC(FMINP, fminp);
7143#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08007144 case NEON_FMLA_H:
7145 fmla(vf, rd, rd, rn, rm);
7146 break;
7147 case NEON_FMLS_H:
7148 fmls(vf, rd, rd, rn, rm);
7149 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007150 case NEON_FCMEQ_H:
7151 fcmp(vf, rd, rn, rm, eq);
7152 break;
7153 case NEON_FCMGE_H:
7154 fcmp(vf, rd, rn, rm, ge);
7155 break;
7156 case NEON_FACGE_H:
7157 fabscmp(vf, rd, rn, rm, ge);
7158 break;
7159 case NEON_FCMGT_H:
7160 fcmp(vf, rd, rn, rm, gt);
7161 break;
7162 case NEON_FACGT_H:
7163 fabscmp(vf, rd, rn, rm, gt);
7164 break;
7165 default:
7166 VIXL_UNIMPLEMENTED();
7167 break;
7168 }
7169}
7170
Carey Williams2809e6c2018-03-13 12:24:16 +00007171void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7172 NEONFormatDecoder nfd(instr);
7173 SimVRegister& rd = ReadVRegister(instr->GetRd());
7174 SimVRegister& rn = ReadVRegister(instr->GetRn());
7175 SimVRegister& rm = ReadVRegister(instr->GetRm());
7176 int rot = 0;
7177 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01007178 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
7179 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01007180 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01007181 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
7182 rot = instr->GetImmRotFcadd();
7183 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01007184 } else {
7185 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01007186 case NEON_SDOT:
7187 sdot(vf, rd, rn, rm);
7188 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007189 case NEON_SQRDMLAH:
7190 sqrdmlah(vf, rd, rn, rm);
7191 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007192 case NEON_UDOT:
7193 udot(vf, rd, rn, rm);
7194 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007195 case NEON_SQRDMLSH:
7196 sqrdmlsh(vf, rd, rn, rm);
7197 break;
7198 default:
7199 VIXL_UNIMPLEMENTED();
7200 break;
7201 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007202 }
7203}
7204
7205
Alexandre Ramesd3832962016-07-04 15:03:43 +01007206void Simulator::VisitNEON3Different(const Instruction* instr) {
7207 NEONFormatDecoder nfd(instr);
7208 VectorFormat vf = nfd.GetVectorFormat();
7209 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7210
7211 SimVRegister& rd = ReadVRegister(instr->GetRd());
7212 SimVRegister& rn = ReadVRegister(instr->GetRn());
7213 SimVRegister& rm = ReadVRegister(instr->GetRm());
7214
7215 switch (instr->Mask(NEON3DifferentMask)) {
7216 case NEON_PMULL:
7217 pmull(vf_l, rd, rn, rm);
7218 break;
7219 case NEON_PMULL2:
7220 pmull2(vf_l, rd, rn, rm);
7221 break;
7222 case NEON_UADDL:
7223 uaddl(vf_l, rd, rn, rm);
7224 break;
7225 case NEON_UADDL2:
7226 uaddl2(vf_l, rd, rn, rm);
7227 break;
7228 case NEON_SADDL:
7229 saddl(vf_l, rd, rn, rm);
7230 break;
7231 case NEON_SADDL2:
7232 saddl2(vf_l, rd, rn, rm);
7233 break;
7234 case NEON_USUBL:
7235 usubl(vf_l, rd, rn, rm);
7236 break;
7237 case NEON_USUBL2:
7238 usubl2(vf_l, rd, rn, rm);
7239 break;
7240 case NEON_SSUBL:
7241 ssubl(vf_l, rd, rn, rm);
7242 break;
7243 case NEON_SSUBL2:
7244 ssubl2(vf_l, rd, rn, rm);
7245 break;
7246 case NEON_SABAL:
7247 sabal(vf_l, rd, rn, rm);
7248 break;
7249 case NEON_SABAL2:
7250 sabal2(vf_l, rd, rn, rm);
7251 break;
7252 case NEON_UABAL:
7253 uabal(vf_l, rd, rn, rm);
7254 break;
7255 case NEON_UABAL2:
7256 uabal2(vf_l, rd, rn, rm);
7257 break;
7258 case NEON_SABDL:
7259 sabdl(vf_l, rd, rn, rm);
7260 break;
7261 case NEON_SABDL2:
7262 sabdl2(vf_l, rd, rn, rm);
7263 break;
7264 case NEON_UABDL:
7265 uabdl(vf_l, rd, rn, rm);
7266 break;
7267 case NEON_UABDL2:
7268 uabdl2(vf_l, rd, rn, rm);
7269 break;
7270 case NEON_SMLAL:
7271 smlal(vf_l, rd, rn, rm);
7272 break;
7273 case NEON_SMLAL2:
7274 smlal2(vf_l, rd, rn, rm);
7275 break;
7276 case NEON_UMLAL:
7277 umlal(vf_l, rd, rn, rm);
7278 break;
7279 case NEON_UMLAL2:
7280 umlal2(vf_l, rd, rn, rm);
7281 break;
7282 case NEON_SMLSL:
7283 smlsl(vf_l, rd, rn, rm);
7284 break;
7285 case NEON_SMLSL2:
7286 smlsl2(vf_l, rd, rn, rm);
7287 break;
7288 case NEON_UMLSL:
7289 umlsl(vf_l, rd, rn, rm);
7290 break;
7291 case NEON_UMLSL2:
7292 umlsl2(vf_l, rd, rn, rm);
7293 break;
7294 case NEON_SMULL:
7295 smull(vf_l, rd, rn, rm);
7296 break;
7297 case NEON_SMULL2:
7298 smull2(vf_l, rd, rn, rm);
7299 break;
7300 case NEON_UMULL:
7301 umull(vf_l, rd, rn, rm);
7302 break;
7303 case NEON_UMULL2:
7304 umull2(vf_l, rd, rn, rm);
7305 break;
7306 case NEON_SQDMLAL:
7307 sqdmlal(vf_l, rd, rn, rm);
7308 break;
7309 case NEON_SQDMLAL2:
7310 sqdmlal2(vf_l, rd, rn, rm);
7311 break;
7312 case NEON_SQDMLSL:
7313 sqdmlsl(vf_l, rd, rn, rm);
7314 break;
7315 case NEON_SQDMLSL2:
7316 sqdmlsl2(vf_l, rd, rn, rm);
7317 break;
7318 case NEON_SQDMULL:
7319 sqdmull(vf_l, rd, rn, rm);
7320 break;
7321 case NEON_SQDMULL2:
7322 sqdmull2(vf_l, rd, rn, rm);
7323 break;
7324 case NEON_UADDW:
7325 uaddw(vf_l, rd, rn, rm);
7326 break;
7327 case NEON_UADDW2:
7328 uaddw2(vf_l, rd, rn, rm);
7329 break;
7330 case NEON_SADDW:
7331 saddw(vf_l, rd, rn, rm);
7332 break;
7333 case NEON_SADDW2:
7334 saddw2(vf_l, rd, rn, rm);
7335 break;
7336 case NEON_USUBW:
7337 usubw(vf_l, rd, rn, rm);
7338 break;
7339 case NEON_USUBW2:
7340 usubw2(vf_l, rd, rn, rm);
7341 break;
7342 case NEON_SSUBW:
7343 ssubw(vf_l, rd, rn, rm);
7344 break;
7345 case NEON_SSUBW2:
7346 ssubw2(vf_l, rd, rn, rm);
7347 break;
7348 case NEON_ADDHN:
7349 addhn(vf, rd, rn, rm);
7350 break;
7351 case NEON_ADDHN2:
7352 addhn2(vf, rd, rn, rm);
7353 break;
7354 case NEON_RADDHN:
7355 raddhn(vf, rd, rn, rm);
7356 break;
7357 case NEON_RADDHN2:
7358 raddhn2(vf, rd, rn, rm);
7359 break;
7360 case NEON_SUBHN:
7361 subhn(vf, rd, rn, rm);
7362 break;
7363 case NEON_SUBHN2:
7364 subhn2(vf, rd, rn, rm);
7365 break;
7366 case NEON_RSUBHN:
7367 rsubhn(vf, rd, rn, rm);
7368 break;
7369 case NEON_RSUBHN2:
7370 rsubhn2(vf, rd, rn, rm);
7371 break;
7372 default:
7373 VIXL_UNIMPLEMENTED();
7374 }
7375}
7376
7377
7378void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7379 NEONFormatDecoder nfd(instr);
7380
Jacob Bramleyca789742018-09-13 14:25:46 +01007381 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7382
Alexandre Ramesd3832962016-07-04 15:03:43 +01007383 SimVRegister& rd = ReadVRegister(instr->GetRd());
7384 SimVRegister& rn = ReadVRegister(instr->GetRn());
7385
Jacob Bramleyca789742018-09-13 14:25:46 +01007386 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7387 VectorFormat vf = nfd.GetVectorFormat(&map_half);
7388 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7389 case NEON_FMAXV_H:
7390 fmaxv(vf, rd, rn);
7391 break;
7392 case NEON_FMINV_H:
7393 fminv(vf, rd, rn);
7394 break;
7395 case NEON_FMAXNMV_H:
7396 fmaxnmv(vf, rd, rn);
7397 break;
7398 case NEON_FMINNMV_H:
7399 fminnmv(vf, rd, rn);
7400 break;
7401 default:
7402 VIXL_UNIMPLEMENTED();
7403 }
7404 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7405 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01007406 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7407
7408 switch (instr->Mask(NEONAcrossLanesFPMask)) {
7409 case NEON_FMAXV:
7410 fmaxv(vf, rd, rn);
7411 break;
7412 case NEON_FMINV:
7413 fminv(vf, rd, rn);
7414 break;
7415 case NEON_FMAXNMV:
7416 fmaxnmv(vf, rd, rn);
7417 break;
7418 case NEON_FMINNMV:
7419 fminnmv(vf, rd, rn);
7420 break;
7421 default:
7422 VIXL_UNIMPLEMENTED();
7423 }
7424 } else {
7425 VectorFormat vf = nfd.GetVectorFormat();
7426
7427 switch (instr->Mask(NEONAcrossLanesMask)) {
7428 case NEON_ADDV:
7429 addv(vf, rd, rn);
7430 break;
7431 case NEON_SMAXV:
7432 smaxv(vf, rd, rn);
7433 break;
7434 case NEON_SMINV:
7435 sminv(vf, rd, rn);
7436 break;
7437 case NEON_UMAXV:
7438 umaxv(vf, rd, rn);
7439 break;
7440 case NEON_UMINV:
7441 uminv(vf, rd, rn);
7442 break;
7443 case NEON_SADDLV:
7444 saddlv(vf, rd, rn);
7445 break;
7446 case NEON_UADDLV:
7447 uaddlv(vf, rd, rn);
7448 break;
7449 default:
7450 VIXL_UNIMPLEMENTED();
7451 }
7452 }
7453}
7454
7455
7456void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7457 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01007458 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007459 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01007460 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007461 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7462
7463 SimVRegister& rd = ReadVRegister(instr->GetRd());
7464 SimVRegister& rn = ReadVRegister(instr->GetRn());
7465
7466 ByElementOp Op = NULL;
7467
7468 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007469 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007470 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007471 int index_hlm = (index << 1) | instr->GetNEONM();
7472
7473 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
7474 // These are oddballs and are best handled as special cases.
7475 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
7476 // - The index is always H:L:M.
7477 case NEON_FMLAL_H_byelement:
7478 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7479 return;
7480 case NEON_FMLAL2_H_byelement:
7481 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7482 return;
7483 case NEON_FMLSL_H_byelement:
7484 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7485 return;
7486 case NEON_FMLSL2_H_byelement:
7487 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7488 return;
7489 }
7490
Alexandre Ramesd3832962016-07-04 15:03:43 +01007491 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007492 rm_reg = rm_low_reg;
7493 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007494 }
7495
7496 switch (instr->Mask(NEONByIndexedElementMask)) {
7497 case NEON_MUL_byelement:
7498 Op = &Simulator::mul;
7499 vf = vf_r;
7500 break;
7501 case NEON_MLA_byelement:
7502 Op = &Simulator::mla;
7503 vf = vf_r;
7504 break;
7505 case NEON_MLS_byelement:
7506 Op = &Simulator::mls;
7507 vf = vf_r;
7508 break;
7509 case NEON_SQDMULH_byelement:
7510 Op = &Simulator::sqdmulh;
7511 vf = vf_r;
7512 break;
7513 case NEON_SQRDMULH_byelement:
7514 Op = &Simulator::sqrdmulh;
7515 vf = vf_r;
7516 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007517 case NEON_SDOT_byelement:
7518 Op = &Simulator::sdot;
7519 vf = vf_r;
7520 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007521 case NEON_SQRDMLAH_byelement:
7522 Op = &Simulator::sqrdmlah;
7523 vf = vf_r;
7524 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007525 case NEON_UDOT_byelement:
7526 Op = &Simulator::udot;
7527 vf = vf_r;
7528 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007529 case NEON_SQRDMLSH_byelement:
7530 Op = &Simulator::sqrdmlsh;
7531 vf = vf_r;
7532 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007533 case NEON_SMULL_byelement:
7534 if (instr->Mask(NEON_Q)) {
7535 Op = &Simulator::smull2;
7536 } else {
7537 Op = &Simulator::smull;
7538 }
7539 break;
7540 case NEON_UMULL_byelement:
7541 if (instr->Mask(NEON_Q)) {
7542 Op = &Simulator::umull2;
7543 } else {
7544 Op = &Simulator::umull;
7545 }
7546 break;
7547 case NEON_SMLAL_byelement:
7548 if (instr->Mask(NEON_Q)) {
7549 Op = &Simulator::smlal2;
7550 } else {
7551 Op = &Simulator::smlal;
7552 }
7553 break;
7554 case NEON_UMLAL_byelement:
7555 if (instr->Mask(NEON_Q)) {
7556 Op = &Simulator::umlal2;
7557 } else {
7558 Op = &Simulator::umlal;
7559 }
7560 break;
7561 case NEON_SMLSL_byelement:
7562 if (instr->Mask(NEON_Q)) {
7563 Op = &Simulator::smlsl2;
7564 } else {
7565 Op = &Simulator::smlsl;
7566 }
7567 break;
7568 case NEON_UMLSL_byelement:
7569 if (instr->Mask(NEON_Q)) {
7570 Op = &Simulator::umlsl2;
7571 } else {
7572 Op = &Simulator::umlsl;
7573 }
7574 break;
7575 case NEON_SQDMULL_byelement:
7576 if (instr->Mask(NEON_Q)) {
7577 Op = &Simulator::sqdmull2;
7578 } else {
7579 Op = &Simulator::sqdmull;
7580 }
7581 break;
7582 case NEON_SQDMLAL_byelement:
7583 if (instr->Mask(NEON_Q)) {
7584 Op = &Simulator::sqdmlal2;
7585 } else {
7586 Op = &Simulator::sqdmlal;
7587 }
7588 break;
7589 case NEON_SQDMLSL_byelement:
7590 if (instr->Mask(NEON_Q)) {
7591 Op = &Simulator::sqdmlsl2;
7592 } else {
7593 Op = &Simulator::sqdmlsl;
7594 }
7595 break;
7596 default:
7597 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01007598 if (instr->GetFPType() == 0) {
7599 rm_reg &= 0xf;
7600 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7601 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007602 index = (index << 1) | instr->GetNEONL();
7603 }
7604
7605 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7606
7607 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01007608 case NEON_FMUL_H_byelement:
7609 vf = vf_half;
7610 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007611 case NEON_FMUL_byelement:
7612 Op = &Simulator::fmul;
7613 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007614 case NEON_FMLA_H_byelement:
7615 vf = vf_half;
7616 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007617 case NEON_FMLA_byelement:
7618 Op = &Simulator::fmla;
7619 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007620 case NEON_FMLS_H_byelement:
7621 vf = vf_half;
7622 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007623 case NEON_FMLS_byelement:
7624 Op = &Simulator::fmls;
7625 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007626 case NEON_FMULX_H_byelement:
7627 vf = vf_half;
7628 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007629 case NEON_FMULX_byelement:
7630 Op = &Simulator::fmulx;
7631 break;
7632 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007633 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00007634 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007635 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00007636 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007637 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007638 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
7639 case NEON_FCMLA_byelement:
7640 vf = vf_r;
7641 fcmla(vf,
7642 rd,
7643 rn,
7644 ReadVRegister(instr->GetRm()),
7645 index,
7646 instr->GetImmRotFcmlaSca());
7647 return;
7648 default:
7649 VIXL_UNIMPLEMENTED();
7650 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007651 }
7652 }
7653
7654 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
7655}
7656
7657
7658void Simulator::VisitNEONCopy(const Instruction* instr) {
7659 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7660 VectorFormat vf = nfd.GetVectorFormat();
7661
7662 SimVRegister& rd = ReadVRegister(instr->GetRd());
7663 SimVRegister& rn = ReadVRegister(instr->GetRn());
7664 int imm5 = instr->GetImmNEON5();
7665 int tz = CountTrailingZeros(imm5, 32);
7666 int reg_index = imm5 >> (tz + 1);
7667
7668 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7669 int imm4 = instr->GetImmNEON4();
7670 int rn_index = imm4 >> tz;
7671 ins_element(vf, rd, reg_index, rn, rn_index);
7672 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7673 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7674 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7675 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7676 value &= MaxUintFromFormat(vf);
7677 WriteXRegister(instr->GetRd(), value);
7678 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7679 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7680 if (instr->GetNEONQ()) {
7681 WriteXRegister(instr->GetRd(), value);
7682 } else {
7683 WriteWRegister(instr->GetRd(), (int32_t)value);
7684 }
7685 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7686 dup_element(vf, rd, rn, reg_index);
7687 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7688 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7689 } else {
7690 VIXL_UNIMPLEMENTED();
7691 }
7692}
7693
7694
7695void Simulator::VisitNEONExtract(const Instruction* instr) {
7696 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7697 VectorFormat vf = nfd.GetVectorFormat();
7698 SimVRegister& rd = ReadVRegister(instr->GetRd());
7699 SimVRegister& rn = ReadVRegister(instr->GetRn());
7700 SimVRegister& rm = ReadVRegister(instr->GetRm());
7701 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7702 int index = instr->GetImmNEONExt();
7703 ext(vf, rd, rn, rm, index);
7704 } else {
7705 VIXL_UNIMPLEMENTED();
7706 }
7707}
7708
7709
7710void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7711 AddrMode addr_mode) {
7712 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7713 VectorFormat vf = nfd.GetVectorFormat();
7714
7715 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7716 int reg_size = RegisterSizeInBytesFromFormat(vf);
7717
7718 int reg[4];
7719 uint64_t addr[4];
7720 for (int i = 0; i < 4; i++) {
7721 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7722 addr[i] = addr_base + (i * reg_size);
7723 }
Jacob Bramley423e5422019-11-13 19:15:55 +00007724 int struct_parts = 1;
7725 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007726 bool log_read = true;
7727
Martyn Capewell32009e32016-10-27 11:00:37 +01007728 // Bit 23 determines whether this is an offset or post-index addressing mode.
7729 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7730 // register or immediate in post-index mode.
7731 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007732 VIXL_UNREACHABLE();
7733 }
7734
7735 // We use the PostIndex mask here, as it works in this case for both Offset
7736 // and PostIndex addressing.
7737 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7738 case NEON_LD1_4v:
7739 case NEON_LD1_4v_post:
7740 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007741 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007742 VIXL_FALLTHROUGH();
7743 case NEON_LD1_3v:
7744 case NEON_LD1_3v_post:
7745 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007746 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007747 VIXL_FALLTHROUGH();
7748 case NEON_LD1_2v:
7749 case NEON_LD1_2v_post:
7750 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007751 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007752 VIXL_FALLTHROUGH();
7753 case NEON_LD1_1v:
7754 case NEON_LD1_1v_post:
7755 ld1(vf, ReadVRegister(reg[0]), addr[0]);
7756 break;
7757 case NEON_ST1_4v:
7758 case NEON_ST1_4v_post:
7759 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007760 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007761 VIXL_FALLTHROUGH();
7762 case NEON_ST1_3v:
7763 case NEON_ST1_3v_post:
7764 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007765 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007766 VIXL_FALLTHROUGH();
7767 case NEON_ST1_2v:
7768 case NEON_ST1_2v_post:
7769 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007770 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007771 VIXL_FALLTHROUGH();
7772 case NEON_ST1_1v:
7773 case NEON_ST1_1v_post:
7774 st1(vf, ReadVRegister(reg[0]), addr[0]);
7775 log_read = false;
7776 break;
7777 case NEON_LD2_post:
7778 case NEON_LD2:
7779 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007780 struct_parts = 2;
7781 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007782 break;
7783 case NEON_ST2:
7784 case NEON_ST2_post:
7785 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007786 struct_parts = 2;
7787 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01007788 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007789 break;
7790 case NEON_LD3_post:
7791 case NEON_LD3:
7792 ld3(vf,
7793 ReadVRegister(reg[0]),
7794 ReadVRegister(reg[1]),
7795 ReadVRegister(reg[2]),
7796 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007797 struct_parts = 3;
7798 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007799 break;
7800 case NEON_ST3:
7801 case NEON_ST3_post:
7802 st3(vf,
7803 ReadVRegister(reg[0]),
7804 ReadVRegister(reg[1]),
7805 ReadVRegister(reg[2]),
7806 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007807 struct_parts = 3;
7808 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01007809 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007810 break;
7811 case NEON_ST4:
7812 case NEON_ST4_post:
7813 st4(vf,
7814 ReadVRegister(reg[0]),
7815 ReadVRegister(reg[1]),
7816 ReadVRegister(reg[2]),
7817 ReadVRegister(reg[3]),
7818 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007819 struct_parts = 4;
7820 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01007821 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007822 break;
7823 case NEON_LD4_post:
7824 case NEON_LD4:
7825 ld4(vf,
7826 ReadVRegister(reg[0]),
7827 ReadVRegister(reg[1]),
7828 ReadVRegister(reg[2]),
7829 ReadVRegister(reg[3]),
7830 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007831 struct_parts = 4;
7832 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007833 break;
7834 default:
7835 VIXL_UNIMPLEMENTED();
7836 }
7837
Jacob Bramley7eb3e212019-11-22 17:28:05 +00007838 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00007839 if (do_trace) {
7840 PrintRegisterFormat print_format =
7841 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
7842 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007843 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00007844 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01007845 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00007846 op = "->";
7847 // Stores don't represent a change to the source register's value, so only
7848 // print the relevant part of the value.
7849 print_format = GetPrintRegPartial(print_format);
7850 }
7851
7852 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
7853 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
7854 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
7855 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007856 }
7857 }
7858
7859 if (addr_mode == PostIndex) {
7860 int rm = instr->GetRm();
7861 // The immediate post index addressing mode is indicated by rm = 31.
7862 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00007863 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01007864 : ReadXRegister(rm);
7865 WriteXRegister(instr->GetRn(), addr_base);
7866 } else {
7867 VIXL_ASSERT(addr_mode == Offset);
7868 }
7869}
7870
7871
7872void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
7873 NEONLoadStoreMultiStructHelper(instr, Offset);
7874}
7875
7876
7877void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
7878 const Instruction* instr) {
7879 NEONLoadStoreMultiStructHelper(instr, PostIndex);
7880}
7881
7882
7883void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
7884 AddrMode addr_mode) {
7885 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7886 int rt = instr->GetRt();
7887
Martyn Capewell32009e32016-10-27 11:00:37 +01007888 // Bit 23 determines whether this is an offset or post-index addressing mode.
7889 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7890 // register or immediate in post-index mode.
7891 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007892 VIXL_UNREACHABLE();
7893 }
7894
7895 // We use the PostIndex mask here, as it works in this case for both Offset
7896 // and PostIndex addressing.
7897 bool do_load = false;
7898
Jacob Bramley423e5422019-11-13 19:15:55 +00007899 bool replicating = false;
7900
Alexandre Ramesd3832962016-07-04 15:03:43 +01007901 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7902 VectorFormat vf_t = nfd.GetVectorFormat();
7903
7904 VectorFormat vf = kFormat16B;
7905 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
7906 case NEON_LD1_b:
7907 case NEON_LD1_b_post:
7908 case NEON_LD2_b:
7909 case NEON_LD2_b_post:
7910 case NEON_LD3_b:
7911 case NEON_LD3_b_post:
7912 case NEON_LD4_b:
7913 case NEON_LD4_b_post:
7914 do_load = true;
7915 VIXL_FALLTHROUGH();
7916 case NEON_ST1_b:
7917 case NEON_ST1_b_post:
7918 case NEON_ST2_b:
7919 case NEON_ST2_b_post:
7920 case NEON_ST3_b:
7921 case NEON_ST3_b_post:
7922 case NEON_ST4_b:
7923 case NEON_ST4_b_post:
7924 break;
7925
7926 case NEON_LD1_h:
7927 case NEON_LD1_h_post:
7928 case NEON_LD2_h:
7929 case NEON_LD2_h_post:
7930 case NEON_LD3_h:
7931 case NEON_LD3_h_post:
7932 case NEON_LD4_h:
7933 case NEON_LD4_h_post:
7934 do_load = true;
7935 VIXL_FALLTHROUGH();
7936 case NEON_ST1_h:
7937 case NEON_ST1_h_post:
7938 case NEON_ST2_h:
7939 case NEON_ST2_h_post:
7940 case NEON_ST3_h:
7941 case NEON_ST3_h_post:
7942 case NEON_ST4_h:
7943 case NEON_ST4_h_post:
7944 vf = kFormat8H;
7945 break;
7946 case NEON_LD1_s:
7947 case NEON_LD1_s_post:
7948 case NEON_LD2_s:
7949 case NEON_LD2_s_post:
7950 case NEON_LD3_s:
7951 case NEON_LD3_s_post:
7952 case NEON_LD4_s:
7953 case NEON_LD4_s_post:
7954 do_load = true;
7955 VIXL_FALLTHROUGH();
7956 case NEON_ST1_s:
7957 case NEON_ST1_s_post:
7958 case NEON_ST2_s:
7959 case NEON_ST2_s_post:
7960 case NEON_ST3_s:
7961 case NEON_ST3_s_post:
7962 case NEON_ST4_s:
7963 case NEON_ST4_s_post: {
7964 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
7965 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
7966 NEON_LD1_d_post);
7967 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
7968 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
7969 NEON_ST1_d_post);
7970 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
7971 break;
7972 }
7973
7974 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00007975 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01007976 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00007977 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01007978 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00007979 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01007980 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00007981 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01007982 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007983 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00007984 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007985 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00007986
Alexandre Ramesd3832962016-07-04 15:03:43 +01007987 default:
7988 VIXL_UNIMPLEMENTED();
7989 }
7990
Alexandre Ramesd3832962016-07-04 15:03:43 +01007991 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
7992 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00007993 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007994 int rt2 = (rt + 1) % kNumberOfVRegisters;
7995 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
7996 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
7997 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
7998 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00007999 reg_count = 1;
8000 if (replicating) {
8001 VIXL_ASSERT(do_load);
8002 ld1r(vf, ReadVRegister(rt), addr);
8003 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008004 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008005 } else {
8006 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008007 }
8008 break;
8009 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00008010 reg_count = 2;
8011 if (replicating) {
8012 VIXL_ASSERT(do_load);
8013 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8014 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008015 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008016 } else {
8017 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008018 }
8019 break;
8020 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00008021 reg_count = 3;
8022 if (replicating) {
8023 VIXL_ASSERT(do_load);
8024 ld3r(vf,
8025 ReadVRegister(rt),
8026 ReadVRegister(rt2),
8027 ReadVRegister(rt3),
8028 addr);
8029 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008030 ld3(vf,
8031 ReadVRegister(rt),
8032 ReadVRegister(rt2),
8033 ReadVRegister(rt3),
8034 lane,
8035 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008036 } else {
8037 st3(vf,
8038 ReadVRegister(rt),
8039 ReadVRegister(rt2),
8040 ReadVRegister(rt3),
8041 lane,
8042 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008043 }
8044 break;
8045 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00008046 reg_count = 4;
8047 if (replicating) {
8048 VIXL_ASSERT(do_load);
8049 ld4r(vf,
8050 ReadVRegister(rt),
8051 ReadVRegister(rt2),
8052 ReadVRegister(rt3),
8053 ReadVRegister(rt4),
8054 addr);
8055 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008056 ld4(vf,
8057 ReadVRegister(rt),
8058 ReadVRegister(rt2),
8059 ReadVRegister(rt3),
8060 ReadVRegister(rt4),
8061 lane,
8062 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008063 } else {
8064 st4(vf,
8065 ReadVRegister(rt),
8066 ReadVRegister(rt2),
8067 ReadVRegister(rt3),
8068 ReadVRegister(rt4),
8069 lane,
8070 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008071 }
8072 break;
8073 default:
8074 VIXL_UNIMPLEMENTED();
8075 }
8076
Jacob Bramley423e5422019-11-13 19:15:55 +00008077 // Trace registers and/or memory writes.
8078 PrintRegisterFormat print_format =
8079 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8080 if (do_load) {
8081 if (ShouldTraceVRegs()) {
8082 if (replicating) {
8083 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8084 } else {
8085 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8086 }
8087 }
8088 } else {
8089 if (ShouldTraceWrites()) {
8090 // Stores don't represent a change to the source register's value, so only
8091 // print the relevant part of the value.
8092 print_format = GetPrintRegPartial(print_format);
8093 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8094 }
8095 }
8096
Alexandre Ramesd3832962016-07-04 15:03:43 +01008097 if (addr_mode == PostIndex) {
8098 int rm = instr->GetRm();
8099 int lane_size = LaneSizeInBytesFromFormat(vf);
8100 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00008101 addr + ((rm == 31) ? (reg_count * lane_size)
8102 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008103 }
8104}
8105
8106
8107void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8108 NEONLoadStoreSingleStructHelper(instr, Offset);
8109}
8110
8111
8112void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8113 const Instruction* instr) {
8114 NEONLoadStoreSingleStructHelper(instr, PostIndex);
8115}
8116
8117
8118void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8119 SimVRegister& rd = ReadVRegister(instr->GetRd());
8120 int cmode = instr->GetNEONCmode();
8121 int cmode_3_1 = (cmode >> 1) & 7;
8122 int cmode_3 = (cmode >> 3) & 1;
8123 int cmode_2 = (cmode >> 2) & 1;
8124 int cmode_1 = (cmode >> 1) & 1;
8125 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01008126 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008127 int q = instr->GetNEONQ();
8128 int op_bit = instr->GetNEONModImmOp();
8129 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01008130 // Find the format and immediate value
8131 uint64_t imm = 0;
8132 VectorFormat vform = kFormatUndefined;
8133 switch (cmode_3_1) {
8134 case 0x0:
8135 case 0x1:
8136 case 0x2:
8137 case 0x3:
8138 vform = (q == 1) ? kFormat4S : kFormat2S;
8139 imm = imm8 << (8 * cmode_3_1);
8140 break;
8141 case 0x4:
8142 case 0x5:
8143 vform = (q == 1) ? kFormat8H : kFormat4H;
8144 imm = imm8 << (8 * cmode_1);
8145 break;
8146 case 0x6:
8147 vform = (q == 1) ? kFormat4S : kFormat2S;
8148 if (cmode_0 == 0) {
8149 imm = imm8 << 8 | 0x000000ff;
8150 } else {
8151 imm = imm8 << 16 | 0x0000ffff;
8152 }
8153 break;
8154 case 0x7:
8155 if (cmode_0 == 0 && op_bit == 0) {
8156 vform = q ? kFormat16B : kFormat8B;
8157 imm = imm8;
8158 } else if (cmode_0 == 0 && op_bit == 1) {
8159 vform = q ? kFormat2D : kFormat1D;
8160 imm = 0;
8161 for (int i = 0; i < 8; ++i) {
8162 if (imm8 & (1 << i)) {
8163 imm |= (UINT64_C(0xff) << (8 * i));
8164 }
8165 }
8166 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01008167 if (half_enc == 1) {
8168 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01008169 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01008170 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008171 vform = q ? kFormat4S : kFormat2S;
8172 imm = FloatToRawbits(instr->GetImmNEONFP32());
8173 } else if (q == 1) {
8174 vform = kFormat2D;
8175 imm = DoubleToRawbits(instr->GetImmNEONFP64());
8176 } else {
8177 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8178 VisitUnallocated(instr);
8179 }
8180 }
8181 break;
8182 default:
8183 VIXL_UNREACHABLE();
8184 break;
8185 }
8186
8187 // Find the operation
8188 NEONModifiedImmediateOp op;
8189 if (cmode_3 == 0) {
8190 if (cmode_0 == 0) {
8191 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8192 } else { // cmode<0> == '1'
8193 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8194 }
8195 } else { // cmode<3> == '1'
8196 if (cmode_2 == 0) {
8197 if (cmode_0 == 0) {
8198 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8199 } else { // cmode<0> == '1'
8200 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8201 }
8202 } else { // cmode<2> == '1'
8203 if (cmode_1 == 0) {
8204 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8205 } else { // cmode<1> == '1'
8206 if (cmode_0 == 0) {
8207 op = NEONModifiedImmediate_MOVI;
8208 } else { // cmode<0> == '1'
8209 op = NEONModifiedImmediate_MOVI;
8210 }
8211 }
8212 }
8213 }
8214
8215 // Call the logic function
8216 if (op == NEONModifiedImmediate_ORR) {
8217 orr(vform, rd, rd, imm);
8218 } else if (op == NEONModifiedImmediate_BIC) {
8219 bic(vform, rd, rd, imm);
8220 } else if (op == NEONModifiedImmediate_MOVI) {
8221 movi(vform, rd, imm);
8222 } else if (op == NEONModifiedImmediate_MVNI) {
8223 mvni(vform, rd, imm);
8224 } else {
8225 VisitUnimplemented(instr);
8226 }
8227}
8228
8229
8230void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8231 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8232 VectorFormat vf = nfd.GetVectorFormat();
8233
8234 SimVRegister& rd = ReadVRegister(instr->GetRd());
8235 SimVRegister& rn = ReadVRegister(instr->GetRn());
8236
8237 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8238 // These instructions all use a two bit size field, except NOT and RBIT,
8239 // which use the field to encode the operation.
8240 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8241 case NEON_CMEQ_zero_scalar:
8242 cmp(vf, rd, rn, 0, eq);
8243 break;
8244 case NEON_CMGE_zero_scalar:
8245 cmp(vf, rd, rn, 0, ge);
8246 break;
8247 case NEON_CMGT_zero_scalar:
8248 cmp(vf, rd, rn, 0, gt);
8249 break;
8250 case NEON_CMLT_zero_scalar:
8251 cmp(vf, rd, rn, 0, lt);
8252 break;
8253 case NEON_CMLE_zero_scalar:
8254 cmp(vf, rd, rn, 0, le);
8255 break;
8256 case NEON_ABS_scalar:
8257 abs(vf, rd, rn);
8258 break;
8259 case NEON_SQABS_scalar:
8260 abs(vf, rd, rn).SignedSaturate(vf);
8261 break;
8262 case NEON_NEG_scalar:
8263 neg(vf, rd, rn);
8264 break;
8265 case NEON_SQNEG_scalar:
8266 neg(vf, rd, rn).SignedSaturate(vf);
8267 break;
8268 case NEON_SUQADD_scalar:
8269 suqadd(vf, rd, rn);
8270 break;
8271 case NEON_USQADD_scalar:
8272 usqadd(vf, rd, rn);
8273 break;
8274 default:
8275 VIXL_UNIMPLEMENTED();
8276 break;
8277 }
8278 } else {
8279 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8280 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8281
8282 // These instructions all use a one bit size field, except SQXTUN, SQXTN
8283 // and UQXTN, which use a two bit size field.
8284 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8285 case NEON_FRECPE_scalar:
8286 frecpe(fpf, rd, rn, fpcr_rounding);
8287 break;
8288 case NEON_FRECPX_scalar:
8289 frecpx(fpf, rd, rn);
8290 break;
8291 case NEON_FRSQRTE_scalar:
8292 frsqrte(fpf, rd, rn);
8293 break;
8294 case NEON_FCMGT_zero_scalar:
8295 fcmp_zero(fpf, rd, rn, gt);
8296 break;
8297 case NEON_FCMGE_zero_scalar:
8298 fcmp_zero(fpf, rd, rn, ge);
8299 break;
8300 case NEON_FCMEQ_zero_scalar:
8301 fcmp_zero(fpf, rd, rn, eq);
8302 break;
8303 case NEON_FCMLE_zero_scalar:
8304 fcmp_zero(fpf, rd, rn, le);
8305 break;
8306 case NEON_FCMLT_zero_scalar:
8307 fcmp_zero(fpf, rd, rn, lt);
8308 break;
8309 case NEON_SCVTF_scalar:
8310 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8311 break;
8312 case NEON_UCVTF_scalar:
8313 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8314 break;
8315 case NEON_FCVTNS_scalar:
8316 fcvts(fpf, rd, rn, FPTieEven);
8317 break;
8318 case NEON_FCVTNU_scalar:
8319 fcvtu(fpf, rd, rn, FPTieEven);
8320 break;
8321 case NEON_FCVTPS_scalar:
8322 fcvts(fpf, rd, rn, FPPositiveInfinity);
8323 break;
8324 case NEON_FCVTPU_scalar:
8325 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8326 break;
8327 case NEON_FCVTMS_scalar:
8328 fcvts(fpf, rd, rn, FPNegativeInfinity);
8329 break;
8330 case NEON_FCVTMU_scalar:
8331 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8332 break;
8333 case NEON_FCVTZS_scalar:
8334 fcvts(fpf, rd, rn, FPZero);
8335 break;
8336 case NEON_FCVTZU_scalar:
8337 fcvtu(fpf, rd, rn, FPZero);
8338 break;
8339 case NEON_FCVTAS_scalar:
8340 fcvts(fpf, rd, rn, FPTieAway);
8341 break;
8342 case NEON_FCVTAU_scalar:
8343 fcvtu(fpf, rd, rn, FPTieAway);
8344 break;
8345 case NEON_FCVTXN_scalar:
8346 // Unlike all of the other FP instructions above, fcvtxn encodes dest
8347 // size S as size<0>=1. There's only one case, so we ignore the form.
8348 VIXL_ASSERT(instr->ExtractBit(22) == 1);
8349 fcvtxn(kFormatS, rd, rn);
8350 break;
8351 default:
8352 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8353 case NEON_SQXTN_scalar:
8354 sqxtn(vf, rd, rn);
8355 break;
8356 case NEON_UQXTN_scalar:
8357 uqxtn(vf, rd, rn);
8358 break;
8359 case NEON_SQXTUN_scalar:
8360 sqxtun(vf, rd, rn);
8361 break;
8362 default:
8363 VIXL_UNIMPLEMENTED();
8364 }
8365 }
8366 }
8367}
8368
8369
Jacob Bramleyca789742018-09-13 14:25:46 +01008370void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8371 VectorFormat fpf = kFormatH;
8372 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8373
8374 SimVRegister& rd = ReadVRegister(instr->GetRd());
8375 SimVRegister& rn = ReadVRegister(instr->GetRn());
8376
8377 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8378 case NEON_FRECPE_H_scalar:
8379 frecpe(fpf, rd, rn, fpcr_rounding);
8380 break;
8381 case NEON_FRECPX_H_scalar:
8382 frecpx(fpf, rd, rn);
8383 break;
8384 case NEON_FRSQRTE_H_scalar:
8385 frsqrte(fpf, rd, rn);
8386 break;
8387 case NEON_FCMGT_H_zero_scalar:
8388 fcmp_zero(fpf, rd, rn, gt);
8389 break;
8390 case NEON_FCMGE_H_zero_scalar:
8391 fcmp_zero(fpf, rd, rn, ge);
8392 break;
8393 case NEON_FCMEQ_H_zero_scalar:
8394 fcmp_zero(fpf, rd, rn, eq);
8395 break;
8396 case NEON_FCMLE_H_zero_scalar:
8397 fcmp_zero(fpf, rd, rn, le);
8398 break;
8399 case NEON_FCMLT_H_zero_scalar:
8400 fcmp_zero(fpf, rd, rn, lt);
8401 break;
8402 case NEON_SCVTF_H_scalar:
8403 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8404 break;
8405 case NEON_UCVTF_H_scalar:
8406 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8407 break;
8408 case NEON_FCVTNS_H_scalar:
8409 fcvts(fpf, rd, rn, FPTieEven);
8410 break;
8411 case NEON_FCVTNU_H_scalar:
8412 fcvtu(fpf, rd, rn, FPTieEven);
8413 break;
8414 case NEON_FCVTPS_H_scalar:
8415 fcvts(fpf, rd, rn, FPPositiveInfinity);
8416 break;
8417 case NEON_FCVTPU_H_scalar:
8418 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8419 break;
8420 case NEON_FCVTMS_H_scalar:
8421 fcvts(fpf, rd, rn, FPNegativeInfinity);
8422 break;
8423 case NEON_FCVTMU_H_scalar:
8424 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8425 break;
8426 case NEON_FCVTZS_H_scalar:
8427 fcvts(fpf, rd, rn, FPZero);
8428 break;
8429 case NEON_FCVTZU_H_scalar:
8430 fcvtu(fpf, rd, rn, FPZero);
8431 break;
8432 case NEON_FCVTAS_H_scalar:
8433 fcvts(fpf, rd, rn, FPTieAway);
8434 break;
8435 case NEON_FCVTAU_H_scalar:
8436 fcvtu(fpf, rd, rn, FPTieAway);
8437 break;
8438 }
8439}
8440
8441
Alexandre Ramesd3832962016-07-04 15:03:43 +01008442void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8443 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8444 VectorFormat vf = nfd.GetVectorFormat();
8445
8446 SimVRegister& rd = ReadVRegister(instr->GetRd());
8447 SimVRegister& rn = ReadVRegister(instr->GetRn());
8448 SimVRegister& rm = ReadVRegister(instr->GetRm());
8449 switch (instr->Mask(NEONScalar3DiffMask)) {
8450 case NEON_SQDMLAL_scalar:
8451 sqdmlal(vf, rd, rn, rm);
8452 break;
8453 case NEON_SQDMLSL_scalar:
8454 sqdmlsl(vf, rd, rn, rm);
8455 break;
8456 case NEON_SQDMULL_scalar:
8457 sqdmull(vf, rd, rn, rm);
8458 break;
8459 default:
8460 VIXL_UNIMPLEMENTED();
8461 }
8462}
8463
8464
8465void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8466 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8467 VectorFormat vf = nfd.GetVectorFormat();
8468
8469 SimVRegister& rd = ReadVRegister(instr->GetRd());
8470 SimVRegister& rn = ReadVRegister(instr->GetRn());
8471 SimVRegister& rm = ReadVRegister(instr->GetRm());
8472
8473 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8474 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8475 switch (instr->Mask(NEONScalar3SameFPMask)) {
8476 case NEON_FMULX_scalar:
8477 fmulx(vf, rd, rn, rm);
8478 break;
8479 case NEON_FACGE_scalar:
8480 fabscmp(vf, rd, rn, rm, ge);
8481 break;
8482 case NEON_FACGT_scalar:
8483 fabscmp(vf, rd, rn, rm, gt);
8484 break;
8485 case NEON_FCMEQ_scalar:
8486 fcmp(vf, rd, rn, rm, eq);
8487 break;
8488 case NEON_FCMGE_scalar:
8489 fcmp(vf, rd, rn, rm, ge);
8490 break;
8491 case NEON_FCMGT_scalar:
8492 fcmp(vf, rd, rn, rm, gt);
8493 break;
8494 case NEON_FRECPS_scalar:
8495 frecps(vf, rd, rn, rm);
8496 break;
8497 case NEON_FRSQRTS_scalar:
8498 frsqrts(vf, rd, rn, rm);
8499 break;
8500 case NEON_FABD_scalar:
8501 fabd(vf, rd, rn, rm);
8502 break;
8503 default:
8504 VIXL_UNIMPLEMENTED();
8505 }
8506 } else {
8507 switch (instr->Mask(NEONScalar3SameMask)) {
8508 case NEON_ADD_scalar:
8509 add(vf, rd, rn, rm);
8510 break;
8511 case NEON_SUB_scalar:
8512 sub(vf, rd, rn, rm);
8513 break;
8514 case NEON_CMEQ_scalar:
8515 cmp(vf, rd, rn, rm, eq);
8516 break;
8517 case NEON_CMGE_scalar:
8518 cmp(vf, rd, rn, rm, ge);
8519 break;
8520 case NEON_CMGT_scalar:
8521 cmp(vf, rd, rn, rm, gt);
8522 break;
8523 case NEON_CMHI_scalar:
8524 cmp(vf, rd, rn, rm, hi);
8525 break;
8526 case NEON_CMHS_scalar:
8527 cmp(vf, rd, rn, rm, hs);
8528 break;
8529 case NEON_CMTST_scalar:
8530 cmptst(vf, rd, rn, rm);
8531 break;
8532 case NEON_USHL_scalar:
8533 ushl(vf, rd, rn, rm);
8534 break;
8535 case NEON_SSHL_scalar:
8536 sshl(vf, rd, rn, rm);
8537 break;
8538 case NEON_SQDMULH_scalar:
8539 sqdmulh(vf, rd, rn, rm);
8540 break;
8541 case NEON_SQRDMULH_scalar:
8542 sqrdmulh(vf, rd, rn, rm);
8543 break;
8544 case NEON_UQADD_scalar:
8545 add(vf, rd, rn, rm).UnsignedSaturate(vf);
8546 break;
8547 case NEON_SQADD_scalar:
8548 add(vf, rd, rn, rm).SignedSaturate(vf);
8549 break;
8550 case NEON_UQSUB_scalar:
8551 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8552 break;
8553 case NEON_SQSUB_scalar:
8554 sub(vf, rd, rn, rm).SignedSaturate(vf);
8555 break;
8556 case NEON_UQSHL_scalar:
8557 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8558 break;
8559 case NEON_SQSHL_scalar:
8560 sshl(vf, rd, rn, rm).SignedSaturate(vf);
8561 break;
8562 case NEON_URSHL_scalar:
8563 ushl(vf, rd, rn, rm).Round(vf);
8564 break;
8565 case NEON_SRSHL_scalar:
8566 sshl(vf, rd, rn, rm).Round(vf);
8567 break;
8568 case NEON_UQRSHL_scalar:
8569 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8570 break;
8571 case NEON_SQRSHL_scalar:
8572 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8573 break;
8574 default:
8575 VIXL_UNIMPLEMENTED();
8576 }
8577 }
8578}
8579
Jacob Bramleyca789742018-09-13 14:25:46 +01008580void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8581 SimVRegister& rd = ReadVRegister(instr->GetRd());
8582 SimVRegister& rn = ReadVRegister(instr->GetRn());
8583 SimVRegister& rm = ReadVRegister(instr->GetRm());
8584
8585 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8586 case NEON_FABD_H_scalar:
8587 fabd(kFormatH, rd, rn, rm);
8588 break;
8589 case NEON_FMULX_H_scalar:
8590 fmulx(kFormatH, rd, rn, rm);
8591 break;
8592 case NEON_FCMEQ_H_scalar:
8593 fcmp(kFormatH, rd, rn, rm, eq);
8594 break;
8595 case NEON_FCMGE_H_scalar:
8596 fcmp(kFormatH, rd, rn, rm, ge);
8597 break;
8598 case NEON_FCMGT_H_scalar:
8599 fcmp(kFormatH, rd, rn, rm, gt);
8600 break;
8601 case NEON_FACGE_H_scalar:
8602 fabscmp(kFormatH, rd, rn, rm, ge);
8603 break;
8604 case NEON_FACGT_H_scalar:
8605 fabscmp(kFormatH, rd, rn, rm, gt);
8606 break;
8607 case NEON_FRECPS_H_scalar:
8608 frecps(kFormatH, rd, rn, rm);
8609 break;
8610 case NEON_FRSQRTS_H_scalar:
8611 frsqrts(kFormatH, rd, rn, rm);
8612 break;
8613 default:
8614 VIXL_UNREACHABLE();
8615 }
8616}
8617
Alexandre Ramesd3832962016-07-04 15:03:43 +01008618
Alexander Gilday43785642018-04-04 13:42:33 +01008619void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8620 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8621 VectorFormat vf = nfd.GetVectorFormat();
8622
8623 SimVRegister& rd = ReadVRegister(instr->GetRd());
8624 SimVRegister& rn = ReadVRegister(instr->GetRn());
8625 SimVRegister& rm = ReadVRegister(instr->GetRm());
8626
8627 switch (instr->Mask(NEONScalar3SameExtraMask)) {
8628 case NEON_SQRDMLAH_scalar:
8629 sqrdmlah(vf, rd, rn, rm);
8630 break;
8631 case NEON_SQRDMLSH_scalar:
8632 sqrdmlsh(vf, rd, rn, rm);
8633 break;
8634 default:
8635 VIXL_UNIMPLEMENTED();
8636 }
8637}
8638
Alexandre Ramesd3832962016-07-04 15:03:43 +01008639void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8640 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8641 VectorFormat vf = nfd.GetVectorFormat();
8642 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8643
8644 SimVRegister& rd = ReadVRegister(instr->GetRd());
8645 SimVRegister& rn = ReadVRegister(instr->GetRn());
8646 ByElementOp Op = NULL;
8647
8648 int rm_reg = instr->GetRm();
8649 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8650 if (instr->GetNEONSize() == 1) {
8651 rm_reg &= 0xf;
8652 index = (index << 1) | instr->GetNEONM();
8653 }
8654
8655 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8656 case NEON_SQDMULL_byelement_scalar:
8657 Op = &Simulator::sqdmull;
8658 break;
8659 case NEON_SQDMLAL_byelement_scalar:
8660 Op = &Simulator::sqdmlal;
8661 break;
8662 case NEON_SQDMLSL_byelement_scalar:
8663 Op = &Simulator::sqdmlsl;
8664 break;
8665 case NEON_SQDMULH_byelement_scalar:
8666 Op = &Simulator::sqdmulh;
8667 vf = vf_r;
8668 break;
8669 case NEON_SQRDMULH_byelement_scalar:
8670 Op = &Simulator::sqrdmulh;
8671 vf = vf_r;
8672 break;
Alexander Gilday43785642018-04-04 13:42:33 +01008673 case NEON_SQRDMLAH_byelement_scalar:
8674 Op = &Simulator::sqrdmlah;
8675 vf = vf_r;
8676 break;
8677 case NEON_SQRDMLSH_byelement_scalar:
8678 Op = &Simulator::sqrdmlsh;
8679 vf = vf_r;
8680 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008681 default:
8682 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8683 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01008684 if (instr->GetFPType() == 0) {
8685 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8686 rm_reg &= 0xf;
8687 vf = kFormatH;
8688 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008689 index = (index << 1) | instr->GetNEONL();
8690 }
8691 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008692 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008693 case NEON_FMUL_byelement_scalar:
8694 Op = &Simulator::fmul;
8695 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008696 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008697 case NEON_FMLA_byelement_scalar:
8698 Op = &Simulator::fmla;
8699 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008700 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008701 case NEON_FMLS_byelement_scalar:
8702 Op = &Simulator::fmls;
8703 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008704 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008705 case NEON_FMULX_byelement_scalar:
8706 Op = &Simulator::fmulx;
8707 break;
8708 default:
8709 VIXL_UNIMPLEMENTED();
8710 }
8711 }
8712
8713 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8714}
8715
8716
8717void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8718 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8719 VectorFormat vf = nfd.GetVectorFormat();
8720
8721 SimVRegister& rd = ReadVRegister(instr->GetRd());
8722 SimVRegister& rn = ReadVRegister(instr->GetRn());
8723
8724 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8725 int imm5 = instr->GetImmNEON5();
8726 int tz = CountTrailingZeros(imm5, 32);
8727 int rn_index = imm5 >> (tz + 1);
8728 dup_element(vf, rd, rn, rn_index);
8729 } else {
8730 VIXL_UNIMPLEMENTED();
8731 }
8732}
8733
8734
8735void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008736 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008737 VectorFormat vf = nfd.GetVectorFormat();
8738
8739 SimVRegister& rd = ReadVRegister(instr->GetRd());
8740 SimVRegister& rn = ReadVRegister(instr->GetRn());
8741 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008742 case NEON_ADDP_scalar: {
8743 // All pairwise operations except ADDP use bit U to differentiate FP16
8744 // from FP32/FP64 variations.
8745 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8746 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008747 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008748 }
8749 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008750 case NEON_FADDP_scalar:
8751 faddp(vf, rd, rn);
8752 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008753 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008754 case NEON_FMAXP_scalar:
8755 fmaxp(vf, rd, rn);
8756 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008757 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008758 case NEON_FMAXNMP_scalar:
8759 fmaxnmp(vf, rd, rn);
8760 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008761 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008762 case NEON_FMINP_scalar:
8763 fminp(vf, rd, rn);
8764 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008765 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008766 case NEON_FMINNMP_scalar:
8767 fminnmp(vf, rd, rn);
8768 break;
8769 default:
8770 VIXL_UNIMPLEMENTED();
8771 }
8772}
8773
8774
8775void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
8776 SimVRegister& rd = ReadVRegister(instr->GetRd());
8777 SimVRegister& rn = ReadVRegister(instr->GetRn());
8778 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8779
8780 static const NEONFormatMap map = {{22, 21, 20, 19},
8781 {NF_UNDEF,
8782 NF_B,
8783 NF_H,
8784 NF_H,
8785 NF_S,
8786 NF_S,
8787 NF_S,
8788 NF_S,
8789 NF_D,
8790 NF_D,
8791 NF_D,
8792 NF_D,
8793 NF_D,
8794 NF_D,
8795 NF_D,
8796 NF_D}};
8797 NEONFormatDecoder nfd(instr, &map);
8798 VectorFormat vf = nfd.GetVectorFormat();
8799
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00008800 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
8801 int immh_immb = instr->GetImmNEONImmhImmb();
8802 int right_shift = (16 << highest_set_bit) - immh_immb;
8803 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008804 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
8805 case NEON_SHL_scalar:
8806 shl(vf, rd, rn, left_shift);
8807 break;
8808 case NEON_SLI_scalar:
8809 sli(vf, rd, rn, left_shift);
8810 break;
8811 case NEON_SQSHL_imm_scalar:
8812 sqshl(vf, rd, rn, left_shift);
8813 break;
8814 case NEON_UQSHL_imm_scalar:
8815 uqshl(vf, rd, rn, left_shift);
8816 break;
8817 case NEON_SQSHLU_scalar:
8818 sqshlu(vf, rd, rn, left_shift);
8819 break;
8820 case NEON_SRI_scalar:
8821 sri(vf, rd, rn, right_shift);
8822 break;
8823 case NEON_SSHR_scalar:
8824 sshr(vf, rd, rn, right_shift);
8825 break;
8826 case NEON_USHR_scalar:
8827 ushr(vf, rd, rn, right_shift);
8828 break;
8829 case NEON_SRSHR_scalar:
8830 sshr(vf, rd, rn, right_shift).Round(vf);
8831 break;
8832 case NEON_URSHR_scalar:
8833 ushr(vf, rd, rn, right_shift).Round(vf);
8834 break;
8835 case NEON_SSRA_scalar:
8836 ssra(vf, rd, rn, right_shift);
8837 break;
8838 case NEON_USRA_scalar:
8839 usra(vf, rd, rn, right_shift);
8840 break;
8841 case NEON_SRSRA_scalar:
8842 srsra(vf, rd, rn, right_shift);
8843 break;
8844 case NEON_URSRA_scalar:
8845 ursra(vf, rd, rn, right_shift);
8846 break;
8847 case NEON_UQSHRN_scalar:
8848 uqshrn(vf, rd, rn, right_shift);
8849 break;
8850 case NEON_UQRSHRN_scalar:
8851 uqrshrn(vf, rd, rn, right_shift);
8852 break;
8853 case NEON_SQSHRN_scalar:
8854 sqshrn(vf, rd, rn, right_shift);
8855 break;
8856 case NEON_SQRSHRN_scalar:
8857 sqrshrn(vf, rd, rn, right_shift);
8858 break;
8859 case NEON_SQSHRUN_scalar:
8860 sqshrun(vf, rd, rn, right_shift);
8861 break;
8862 case NEON_SQRSHRUN_scalar:
8863 sqrshrun(vf, rd, rn, right_shift);
8864 break;
8865 case NEON_FCVTZS_imm_scalar:
8866 fcvts(vf, rd, rn, FPZero, right_shift);
8867 break;
8868 case NEON_FCVTZU_imm_scalar:
8869 fcvtu(vf, rd, rn, FPZero, right_shift);
8870 break;
8871 case NEON_SCVTF_imm_scalar:
8872 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
8873 break;
8874 case NEON_UCVTF_imm_scalar:
8875 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
8876 break;
8877 default:
8878 VIXL_UNIMPLEMENTED();
8879 }
8880}
8881
8882
8883void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
8884 SimVRegister& rd = ReadVRegister(instr->GetRd());
8885 SimVRegister& rn = ReadVRegister(instr->GetRn());
8886 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8887
8888 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
8889 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
8890 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01008891 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
8892 NF_4H, NF_8H, NF_4H, NF_8H,
8893 NF_2S, NF_4S, NF_2S, NF_4S,
8894 NF_2S, NF_4S, NF_2S, NF_4S,
8895 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
8896 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
8897 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
8898 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01008899 NEONFormatDecoder nfd(instr, &map);
8900 VectorFormat vf = nfd.GetVectorFormat();
8901
8902 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
8903 static const NEONFormatMap map_l =
8904 {{22, 21, 20, 19},
8905 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
8906 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
8907
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00008908 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
8909 int immh_immb = instr->GetImmNEONImmhImmb();
8910 int right_shift = (16 << highest_set_bit) - immh_immb;
8911 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008912
8913 switch (instr->Mask(NEONShiftImmediateMask)) {
8914 case NEON_SHL:
8915 shl(vf, rd, rn, left_shift);
8916 break;
8917 case NEON_SLI:
8918 sli(vf, rd, rn, left_shift);
8919 break;
8920 case NEON_SQSHLU:
8921 sqshlu(vf, rd, rn, left_shift);
8922 break;
8923 case NEON_SRI:
8924 sri(vf, rd, rn, right_shift);
8925 break;
8926 case NEON_SSHR:
8927 sshr(vf, rd, rn, right_shift);
8928 break;
8929 case NEON_USHR:
8930 ushr(vf, rd, rn, right_shift);
8931 break;
8932 case NEON_SRSHR:
8933 sshr(vf, rd, rn, right_shift).Round(vf);
8934 break;
8935 case NEON_URSHR:
8936 ushr(vf, rd, rn, right_shift).Round(vf);
8937 break;
8938 case NEON_SSRA:
8939 ssra(vf, rd, rn, right_shift);
8940 break;
8941 case NEON_USRA:
8942 usra(vf, rd, rn, right_shift);
8943 break;
8944 case NEON_SRSRA:
8945 srsra(vf, rd, rn, right_shift);
8946 break;
8947 case NEON_URSRA:
8948 ursra(vf, rd, rn, right_shift);
8949 break;
8950 case NEON_SQSHL_imm:
8951 sqshl(vf, rd, rn, left_shift);
8952 break;
8953 case NEON_UQSHL_imm:
8954 uqshl(vf, rd, rn, left_shift);
8955 break;
8956 case NEON_SCVTF_imm:
8957 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
8958 break;
8959 case NEON_UCVTF_imm:
8960 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
8961 break;
8962 case NEON_FCVTZS_imm:
8963 fcvts(vf, rd, rn, FPZero, right_shift);
8964 break;
8965 case NEON_FCVTZU_imm:
8966 fcvtu(vf, rd, rn, FPZero, right_shift);
8967 break;
8968 case NEON_SSHLL:
8969 vf = vf_l;
8970 if (instr->Mask(NEON_Q)) {
8971 sshll2(vf, rd, rn, left_shift);
8972 } else {
8973 sshll(vf, rd, rn, left_shift);
8974 }
8975 break;
8976 case NEON_USHLL:
8977 vf = vf_l;
8978 if (instr->Mask(NEON_Q)) {
8979 ushll2(vf, rd, rn, left_shift);
8980 } else {
8981 ushll(vf, rd, rn, left_shift);
8982 }
8983 break;
8984 case NEON_SHRN:
8985 if (instr->Mask(NEON_Q)) {
8986 shrn2(vf, rd, rn, right_shift);
8987 } else {
8988 shrn(vf, rd, rn, right_shift);
8989 }
8990 break;
8991 case NEON_RSHRN:
8992 if (instr->Mask(NEON_Q)) {
8993 rshrn2(vf, rd, rn, right_shift);
8994 } else {
8995 rshrn(vf, rd, rn, right_shift);
8996 }
8997 break;
8998 case NEON_UQSHRN:
8999 if (instr->Mask(NEON_Q)) {
9000 uqshrn2(vf, rd, rn, right_shift);
9001 } else {
9002 uqshrn(vf, rd, rn, right_shift);
9003 }
9004 break;
9005 case NEON_UQRSHRN:
9006 if (instr->Mask(NEON_Q)) {
9007 uqrshrn2(vf, rd, rn, right_shift);
9008 } else {
9009 uqrshrn(vf, rd, rn, right_shift);
9010 }
9011 break;
9012 case NEON_SQSHRN:
9013 if (instr->Mask(NEON_Q)) {
9014 sqshrn2(vf, rd, rn, right_shift);
9015 } else {
9016 sqshrn(vf, rd, rn, right_shift);
9017 }
9018 break;
9019 case NEON_SQRSHRN:
9020 if (instr->Mask(NEON_Q)) {
9021 sqrshrn2(vf, rd, rn, right_shift);
9022 } else {
9023 sqrshrn(vf, rd, rn, right_shift);
9024 }
9025 break;
9026 case NEON_SQSHRUN:
9027 if (instr->Mask(NEON_Q)) {
9028 sqshrun2(vf, rd, rn, right_shift);
9029 } else {
9030 sqshrun(vf, rd, rn, right_shift);
9031 }
9032 break;
9033 case NEON_SQRSHRUN:
9034 if (instr->Mask(NEON_Q)) {
9035 sqrshrun2(vf, rd, rn, right_shift);
9036 } else {
9037 sqrshrun(vf, rd, rn, right_shift);
9038 }
9039 break;
9040 default:
9041 VIXL_UNIMPLEMENTED();
9042 }
9043}
9044
9045
9046void Simulator::VisitNEONTable(const Instruction* instr) {
9047 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9048 VectorFormat vf = nfd.GetVectorFormat();
9049
9050 SimVRegister& rd = ReadVRegister(instr->GetRd());
9051 SimVRegister& rn = ReadVRegister(instr->GetRn());
9052 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9053 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9054 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9055 SimVRegister& rm = ReadVRegister(instr->GetRm());
9056
9057 switch (instr->Mask(NEONTableMask)) {
9058 case NEON_TBL_1v:
9059 tbl(vf, rd, rn, rm);
9060 break;
9061 case NEON_TBL_2v:
9062 tbl(vf, rd, rn, rn2, rm);
9063 break;
9064 case NEON_TBL_3v:
9065 tbl(vf, rd, rn, rn2, rn3, rm);
9066 break;
9067 case NEON_TBL_4v:
9068 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9069 break;
9070 case NEON_TBX_1v:
9071 tbx(vf, rd, rn, rm);
9072 break;
9073 case NEON_TBX_2v:
9074 tbx(vf, rd, rn, rn2, rm);
9075 break;
9076 case NEON_TBX_3v:
9077 tbx(vf, rd, rn, rn2, rn3, rm);
9078 break;
9079 case NEON_TBX_4v:
9080 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9081 break;
9082 default:
9083 VIXL_UNIMPLEMENTED();
9084 }
9085}
9086
9087
9088void Simulator::VisitNEONPerm(const Instruction* instr) {
9089 NEONFormatDecoder nfd(instr);
9090 VectorFormat vf = nfd.GetVectorFormat();
9091
9092 SimVRegister& rd = ReadVRegister(instr->GetRd());
9093 SimVRegister& rn = ReadVRegister(instr->GetRn());
9094 SimVRegister& rm = ReadVRegister(instr->GetRm());
9095
9096 switch (instr->Mask(NEONPermMask)) {
9097 case NEON_TRN1:
9098 trn1(vf, rd, rn, rm);
9099 break;
9100 case NEON_TRN2:
9101 trn2(vf, rd, rn, rm);
9102 break;
9103 case NEON_UZP1:
9104 uzp1(vf, rd, rn, rm);
9105 break;
9106 case NEON_UZP2:
9107 uzp2(vf, rd, rn, rm);
9108 break;
9109 case NEON_ZIP1:
9110 zip1(vf, rd, rn, rm);
9111 break;
9112 case NEON_ZIP2:
9113 zip2(vf, rd, rn, rm);
9114 break;
9115 default:
9116 VIXL_UNIMPLEMENTED();
9117 }
9118}
9119
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009120void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00009121 SimVRegister& zd = ReadVRegister(instr->GetRd());
9122 SimVRegister& zn = ReadVRegister(instr->GetRn());
9123 SimVRegister& zm = ReadVRegister(instr->GetRm());
9124 SimVRegister temp;
9125
9126 VectorFormat vform = kFormatVnD;
9127 mov(vform, temp, zm);
9128
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009129 switch (instr->Mask(SVEAddressGenerationMask)) {
9130 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009131 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009132 break;
9133 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009134 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009135 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00009136 case ADR_z_az_s_same_scaled:
9137 vform = kFormatVnS;
9138 break;
9139 case ADR_z_az_d_same_scaled:
9140 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009141 break;
9142 default:
9143 VIXL_UNIMPLEMENTED();
9144 break;
9145 }
Martyn Capewell48522f52020-03-16 15:31:19 +00009146
9147 int shift_amount = instr->ExtractBits(11, 10);
9148 shl(vform, temp, temp, shift_amount);
9149 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009150}
9151
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009152void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9153 const Instruction* instr) {
9154 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07009155 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009156 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009157 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07009158 case ORR_z_zi: {
9159 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9160 uint64_t imm = instr->GetSVEImmLogical();
9161 // Valid immediate is a non-zero bits
9162 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009163 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9164 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07009165 SVEFormatFromLaneSizeInBytesLog2(lane_size),
9166 ReadVRegister(instr->GetRd()),
9167 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009168 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07009169 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009170 default:
9171 VIXL_UNIMPLEMENTED();
9172 break;
9173 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009174}
9175
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009176void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9177 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9178 case DUPM_z_i: {
9179 /* DUPM uses the same lane size and immediate encoding as bitwise logical
9180 * immediate instructions. */
9181 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9182 uint64_t imm = instr->GetSVEImmLogical();
9183 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9184 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9185 break;
9186 }
9187 default:
9188 VIXL_UNIMPLEMENTED();
9189 break;
9190 }
9191}
9192
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009193void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07009194 SimVRegister& zd = ReadVRegister(instr->GetRd());
9195 SimVRegister& zn = ReadVRegister(instr->GetRn());
9196 SimVRegister& zm = ReadVRegister(instr->GetRm());
9197 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9198
TatWai Chong13634762019-07-16 16:20:45 -07009199 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07009200 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009201 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009202 logical_op = AND;
9203 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009204 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009205 logical_op = BIC;
9206 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009207 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009208 logical_op = EOR;
9209 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07009210 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009211 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009212 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009213 default:
TatWai Chong13634762019-07-16 16:20:45 -07009214 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009215 VIXL_UNIMPLEMENTED();
9216 break;
9217 }
TatWai Chong13634762019-07-16 16:20:45 -07009218 // Lane size of registers is irrelevant to the bitwise operations, so perform
9219 // the operation on D-sized lanes.
9220 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009221}
9222
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009223void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00009224 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9225 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9226
9227 SimVRegister scratch;
9228 SimVRegister result;
9229
9230 bool for_division = false;
9231 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009232 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009233 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009234 shift_op = ASR;
9235 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009236 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009237 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009238 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009239 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009240 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009241 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009242 break;
9243 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009244 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009245 break;
9246 default:
9247 VIXL_UNIMPLEMENTED();
9248 break;
9249 }
Martyn Capewell83e86612020-02-19 15:46:15 +00009250
9251 std::pair<int, int> shift_and_lane_size =
9252 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9253 unsigned lane_size = shift_and_lane_size.second;
9254 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9255 int shift_dist = shift_and_lane_size.first;
9256
9257 if ((shift_op == ASR) && for_division) {
9258 asrd(vform, result, zdn, shift_dist);
9259 } else {
9260 if (shift_op == LSL) {
9261 // Shift distance is computed differently for LSL. Convert the result.
9262 shift_dist = (8 << lane_size) - shift_dist;
9263 }
9264 dup_immediate(vform, scratch, shift_dist);
9265 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9266 }
9267 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009268}
9269
9270void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9271 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009272 VectorFormat vform = instr->GetSVEVectorFormat();
9273 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9274 SimVRegister& zm = ReadVRegister(instr->GetRn());
9275 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9276
9277 SimVRegister result;
9278 SimVRegister shiftand; // Vector to be shifted.
9279 SimVRegister shiftor; // Vector shift amount.
9280
9281 Shift shift_op = ASR;
9282 mov(vform, shiftand, zdn);
9283 mov(vform, shiftor, zm);
9284
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009285 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
9286 case ASRR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009287 mov(vform, shiftand, zm);
9288 mov(vform, shiftor, zdn);
9289 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009290 case ASR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009291 break;
9292 case LSLR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009293 mov(vform, shiftand, zm);
9294 mov(vform, shiftor, zdn);
9295 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009296 case LSL_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009297 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009298 break;
9299 case LSRR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009300 mov(vform, shiftand, zm);
9301 mov(vform, shiftor, zdn);
9302 VIXL_FALLTHROUGH();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009303 case LSR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009304 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009305 break;
9306 default:
9307 VIXL_UNIMPLEMENTED();
9308 break;
9309 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009310 SVEBitwiseShiftHelper(shift_op,
9311 vform,
9312 result,
9313 shiftand,
9314 shiftor,
9315 /* is_wide_elements = */ false);
9316 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009317}
9318
9319void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9320 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009321 VectorFormat vform = instr->GetSVEVectorFormat();
9322 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9323 SimVRegister& zm = ReadVRegister(instr->GetRn());
9324 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9325
9326 SimVRegister result;
9327 Shift shift_op = ASR;
9328
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009329 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9330 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009331 break;
9332 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009333 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009334 break;
9335 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009336 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009337 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009338 default:
9339 VIXL_UNIMPLEMENTED();
9340 break;
9341 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009342 SVEBitwiseShiftHelper(shift_op,
9343 vform,
9344 result,
9345 zdn,
9346 zm,
9347 /* is_wide_elements = */ true);
9348 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009349}
9350
9351void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08009352 SimVRegister& zd = ReadVRegister(instr->GetRd());
9353 SimVRegister& zn = ReadVRegister(instr->GetRn());
9354
9355 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009356 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9357 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009358 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009359 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009360 break;
9361 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009362 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009363 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009364 break;
9365 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08009366 case LSR_z_zw:
9367 shift_op = LSR;
9368 break;
9369 default:
9370 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009371 VIXL_UNIMPLEMENTED();
9372 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08009373 }
9374
9375 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9376 case ASR_z_zi:
9377 case LSL_z_zi:
9378 case LSR_z_zi: {
9379 SimVRegister scratch;
9380 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00009381 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08009382 unsigned lane_size = shift_and_lane_size.second;
9383 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9384 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00009385 int shift_dist = shift_and_lane_size.first;
9386 if (shift_op == LSL) {
9387 // Shift distance is computed differently for LSL. Convert the result.
9388 shift_dist = (8 << lane_size) - shift_dist;
9389 }
9390 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08009391 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9392 break;
9393 }
9394 case ASR_z_zw:
9395 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009396 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009397 SVEBitwiseShiftHelper(shift_op,
9398 instr->GetSVEVectorFormat(),
9399 zd,
9400 zn,
9401 ReadVRegister(instr->GetRm()),
9402 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009403 break;
9404 default:
9405 VIXL_UNIMPLEMENTED();
9406 break;
9407 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009408}
9409
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009410void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00009411 // Although the instructions have a separate encoding class, the lane size is
9412 // encoded in the same way as most other SVE instructions.
9413 VectorFormat vform = instr->GetSVEVectorFormat();
9414
9415 int pattern = instr->GetImmSVEPredicateConstraint();
9416 int count = GetPredicateConstraintLaneCount(vform, pattern);
9417 int multiplier = instr->ExtractBits(19, 16) + 1;
9418
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009419 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009420 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009421 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009422 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009423 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009424 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009425 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009426 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009427 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009428 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009429 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009430 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009431 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009432 default:
9433 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00009434 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009435 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00009436
9437 WriteXRegister(instr->GetRd(),
9438 IncDecN(ReadXRegister(instr->GetRd()),
9439 count * multiplier,
9440 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009441}
9442
9443void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009444 VectorFormat vform = instr->GetSVEVectorFormat();
9445 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9446 VIXL_UNIMPLEMENTED();
9447 }
9448
9449 int pattern = instr->GetImmSVEPredicateConstraint();
9450 int count = GetPredicateConstraintLaneCount(vform, pattern);
9451 int multiplier = instr->ExtractBits(19, 16) + 1;
9452
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009453 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9454 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009455 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009456 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009457 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009458 break;
9459 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009460 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009461 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009462 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009463 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009464 default:
9465 VIXL_UNIMPLEMENTED();
9466 break;
9467 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009468
9469 SimVRegister& zd = ReadVRegister(instr->GetRd());
9470 SimVRegister scratch;
9471 dup_immediate(vform,
9472 scratch,
9473 IncDecN(0,
9474 count * multiplier,
9475 LaneSizeInBitsFromFormat(vform)));
9476 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009477}
9478
9479void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9480 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009481 // Although the instructions have a separate encoding class, the lane size is
9482 // encoded in the same way as most other SVE instructions.
9483 VectorFormat vform = instr->GetSVEVectorFormat();
9484
9485 int pattern = instr->GetImmSVEPredicateConstraint();
9486 int count = GetPredicateConstraintLaneCount(vform, pattern);
9487 int multiplier = instr->ExtractBits(19, 16) + 1;
9488
9489 unsigned width = kXRegSize;
9490 bool is_signed = false;
9491
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009492 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009493 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009494 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009495 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009496 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009497 width = kWRegSize;
9498 VIXL_FALLTHROUGH();
9499 case SQDECB_r_rs_x:
9500 case SQDECD_r_rs_x:
9501 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009502 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009503 is_signed = true;
9504 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009505 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009506 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009507 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009508 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009509 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009510 width = kWRegSize;
9511 VIXL_FALLTHROUGH();
9512 case SQINCB_r_rs_x:
9513 case SQINCD_r_rs_x:
9514 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009515 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009516 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009517 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009518 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009519 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009520 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009521 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009522 width = kWRegSize;
9523 VIXL_FALLTHROUGH();
9524 case UQDECB_r_rs_x:
9525 case UQDECD_r_rs_x:
9526 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009527 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009528 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009529 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009530 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009531 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009532 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009533 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009534 width = kWRegSize;
9535 VIXL_FALLTHROUGH();
9536 case UQINCB_r_rs_x:
9537 case UQINCD_r_rs_x:
9538 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009539 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009540 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009541 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009542 default:
9543 VIXL_UNIMPLEMENTED();
9544 break;
9545 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009546
9547 WriteXRegister(instr->GetRd(),
9548 IncDecN(ReadXRegister(instr->GetRd()),
9549 count * multiplier,
9550 width,
9551 true,
9552 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009553}
9554
9555void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9556 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009557 VectorFormat vform = instr->GetSVEVectorFormat();
9558 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9559 VIXL_UNIMPLEMENTED();
9560 }
9561
9562 int pattern = instr->GetImmSVEPredicateConstraint();
9563 int count = GetPredicateConstraintLaneCount(vform, pattern);
9564 int multiplier = instr->ExtractBits(19, 16) + 1;
9565
9566 SimVRegister& zd = ReadVRegister(instr->GetRd());
9567 SimVRegister scratch;
9568 dup_immediate(vform,
9569 scratch,
9570 IncDecN(0,
9571 count * multiplier,
9572 LaneSizeInBitsFromFormat(vform)));
9573
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009574 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9575 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009576 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009577 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009578 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009579 break;
9580 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009581 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009582 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009583 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009584 break;
9585 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009586 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009587 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009588 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009589 break;
9590 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009591 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009592 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009593 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009594 break;
9595 default:
9596 VIXL_UNIMPLEMENTED();
9597 break;
9598 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009599}
9600
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009601void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009602 switch (instr->Mask(SVEElementCountMask)) {
9603 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009604 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009605 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009606 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00009607 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009608 break;
9609 default:
9610 VIXL_UNIMPLEMENTED();
9611 break;
9612 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00009613
9614 // Although the instructions are separated, the lane size is encoded in the
9615 // same way as most other SVE instructions.
9616 VectorFormat vform = instr->GetSVEVectorFormat();
9617
9618 int pattern = instr->GetImmSVEPredicateConstraint();
9619 int count = GetPredicateConstraintLaneCount(vform, pattern);
9620 int multiplier = instr->ExtractBits(19, 16) + 1;
9621 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009622}
9623
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009624void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009625 VectorFormat vform = instr->GetSVEVectorFormat();
9626 SimVRegister& vdn = ReadVRegister(instr->GetRd());
9627 SimVRegister& zm = ReadVRegister(instr->GetRn());
9628 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9629
Martyn Capewell310a0822020-09-08 20:09:17 +01009630 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9631
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009632 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9633 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009634 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009635 break;
9636 default:
9637 VIXL_UNIMPLEMENTED();
9638 break;
9639 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009640}
9641
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009642void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07009643 VectorFormat vform = instr->GetSVEVectorFormat();
9644 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9645 SimVRegister& zm = ReadVRegister(instr->GetRn());
9646 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9647
Martyn Capewell310a0822020-09-08 20:09:17 +01009648 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
TatWai Chongd316c5e2019-10-16 12:22:10 -07009649
Martyn Capewell310a0822020-09-08 20:09:17 +01009650 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009651 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009652 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009653 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009654 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009655 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009656 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009657 break;
9658 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009659 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009660 break;
9661 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009662 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009663 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009664 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009665 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009666 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009667 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009668 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009669 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009670 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009671 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009672 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009673 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009674 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009675 break;
9676 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009677 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009678 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009679 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009680 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009681 break;
9682 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009683 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009684 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009685 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009686 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009687 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009688 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009689 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009690 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009691 default:
9692 VIXL_UNIMPLEMENTED();
9693 break;
9694 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07009695 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009696}
9697
9698void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9699 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00009700 VectorFormat vform = instr->GetSVEVectorFormat();
9701 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9702 VIXL_UNIMPLEMENTED();
9703 }
9704
9705 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9706 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9707 SimVRegister result;
9708
9709 int i1 = instr->ExtractBit(5);
9710 SimVRegister add_sub_imm, min_max_imm, mul_imm;
9711 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9712 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9713 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9714 dup_immediate(vform, add_sub_imm, i1 ? one : half);
9715 dup_immediate(vform, min_max_imm, i1 ? one : 0);
9716 dup_immediate(vform, mul_imm, i1 ? two : half);
9717
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009718 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9719 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009720 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009721 break;
9722 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009723 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009724 break;
9725 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009726 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009727 break;
9728 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009729 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009730 break;
9731 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009732 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009733 break;
9734 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009735 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009736 break;
9737 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009738 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009739 break;
9740 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009741 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009742 break;
9743 default:
9744 VIXL_UNIMPLEMENTED();
9745 break;
9746 }
Martyn Capewella2fadc22020-01-16 16:09:55 +00009747 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009748}
9749
9750void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009751 VectorFormat vform = instr->GetSVEVectorFormat();
9752 SimVRegister& zd = ReadVRegister(instr->GetRd());
9753 SimVRegister& zm = ReadVRegister(instr->GetRn());
9754
Martyn Capewell310a0822020-09-08 20:09:17 +01009755 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9756
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009757 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009758 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009759 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009760 break;
9761 default:
9762 VIXL_UNIMPLEMENTED();
9763 break;
9764 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009765}
9766
9767void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -07009768 VectorFormat vform = instr->GetSVEVectorFormat();
9769 SimVRegister& zd = ReadVRegister(instr->GetRd());
9770 SimVRegister& zn = ReadVRegister(instr->GetRn());
9771 SimVRegister& zm = ReadVRegister(instr->GetRm());
9772
Martyn Capewell310a0822020-09-08 20:09:17 +01009773 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9774
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009775 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
9776 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009777 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009778 break;
9779 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009780 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009781 break;
9782 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009783 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009784 break;
9785 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009786 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009787 break;
9788 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009789 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009790 break;
9791 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009792 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009793 break;
9794 default:
9795 VIXL_UNIMPLEMENTED();
9796 break;
9797 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009798}
9799
9800void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -08009801 SimPRegister& pd = ReadPRegister(instr->GetPd());
9802 SimVRegister& zn = ReadVRegister(instr->GetRn());
9803 SimVRegister& zm = ReadVRegister(instr->GetRm());
9804 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9805 VectorFormat vform = instr->GetSVEVectorFormat();
9806 SimVRegister result;
9807
Martyn Capewell310a0822020-09-08 20:09:17 +01009808 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9809
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009810 switch (instr->Mask(SVEFPCompareVectorsMask)) {
9811 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009812 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009813 break;
9814 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009815 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009816 break;
9817 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009818 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009819 break;
9820 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009821 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009822 break;
9823 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009824 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009825 break;
9826 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009827 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009828 break;
9829 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009830 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009831 break;
9832 default:
9833 VIXL_UNIMPLEMENTED();
9834 break;
9835 }
TatWai Chong47c26842020-02-10 01:51:32 -08009836
9837 ExtractFromSimVRegister(vform, pd, result);
9838 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009839}
9840
9841void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -08009842 SimPRegister& pd = ReadPRegister(instr->GetPd());
9843 SimVRegister& zn = ReadVRegister(instr->GetRn());
9844 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9845 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chonge3775132020-02-16 22:13:17 -08009846
Martyn Capewell310a0822020-09-08 20:09:17 +01009847 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9848
9849 SimVRegister result;
TatWai Chonge3775132020-02-16 22:13:17 -08009850 SimVRegister zeros;
9851 dup_immediate(kFormatVnD, zeros, 0);
9852
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009853 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
9854 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009855 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009856 break;
9857 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009858 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009859 break;
9860 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009861 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009862 break;
9863 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009864 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009865 break;
9866 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009867 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009868 break;
9869 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08009870 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009871 break;
9872 default:
9873 VIXL_UNIMPLEMENTED();
9874 break;
9875 }
TatWai Chonge3775132020-02-16 22:13:17 -08009876
9877 ExtractFromSimVRegister(vform, pd, result);
9878 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009879}
9880
9881void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +00009882 VectorFormat vform = instr->GetSVEVectorFormat();
9883
9884 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9885 VIXL_UNIMPLEMENTED();
9886 }
9887
9888 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9889 SimVRegister& zm = ReadVRegister(instr->GetRn());
9890 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9891 int rot = instr->ExtractBit(16);
9892
9893 SimVRegister result;
9894
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009895 switch (instr->Mask(SVEFPComplexAdditionMask)) {
9896 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +00009897 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009898 break;
9899 default:
9900 VIXL_UNIMPLEMENTED();
9901 break;
9902 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +00009903 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009904}
9905
9906void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +01009907 VectorFormat vform = instr->GetSVEVectorFormat();
9908
9909 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9910 VIXL_UNIMPLEMENTED();
9911 }
9912
9913 SimVRegister& zda = ReadVRegister(instr->GetRd());
9914 SimVRegister& zn = ReadVRegister(instr->GetRn());
9915 SimVRegister& zm = ReadVRegister(instr->GetRm());
9916 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9917 int rot = instr->ExtractBits(14, 13);
9918
9919 SimVRegister result;
9920
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009921 switch (instr->Mask(SVEFPComplexMulAddMask)) {
9922 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +01009923 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009924 break;
9925 default:
9926 VIXL_UNIMPLEMENTED();
9927 break;
9928 }
Martyn Capewell75f1c432020-03-30 09:23:27 +01009929 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009930}
9931
9932void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +01009933 SimVRegister& zda = ReadVRegister(instr->GetRd());
9934 SimVRegister& zn = ReadVRegister(instr->GetRn());
9935 int rot = instr->ExtractBits(11, 10);
9936 unsigned zm_code = instr->GetRm();
9937 int index = -1;
9938 VectorFormat vform, vform_dup;
9939
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009940 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
9941 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +01009942 vform = kFormatVnH;
9943 vform_dup = kFormatVnS;
9944 index = zm_code >> 3;
9945 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009946 break;
9947 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +01009948 vform = kFormatVnS;
9949 vform_dup = kFormatVnD;
9950 index = zm_code >> 4;
9951 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009952 break;
9953 default:
9954 VIXL_UNIMPLEMENTED();
9955 break;
9956 }
Martyn Capewelle4886e52020-03-30 09:28:52 +01009957
9958 if (index >= 0) {
9959 SimVRegister temp;
9960 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
9961 fcmla(vform, zda, zn, temp, zda, rot);
9962 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009963}
9964
Martyn Capewell894962f2020-02-05 15:46:44 +00009965typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
9966 LogicVRegister dst,
9967 const LogicVRegister& src);
9968
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009969void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +00009970 VectorFormat vform = instr->GetSVEVectorFormat();
9971 SimVRegister& vd = ReadVRegister(instr->GetRd());
9972 SimVRegister& zn = ReadVRegister(instr->GetRn());
9973 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9974 int lane_size = LaneSizeInBitsFromFormat(vform);
9975
9976 uint64_t inactive_value = 0;
9977 FastReduceFn fn = nullptr;
9978
Martyn Capewell310a0822020-09-08 20:09:17 +01009979 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9980
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009981 switch (instr->Mask(SVEFPFastReductionMask)) {
9982 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00009983 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009984 break;
9985 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00009986 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
9987 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009988 break;
9989 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00009990 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
9991 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009992 break;
9993 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00009994 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
9995 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009996 break;
9997 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00009998 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
9999 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010000 break;
10001 default:
10002 VIXL_UNIMPLEMENTED();
10003 break;
10004 }
Martyn Capewell894962f2020-02-05 15:46:44 +000010005
10006 SimVRegister scratch;
10007 dup_immediate(vform, scratch, inactive_value);
10008 mov_merging(vform, scratch, pg, zn);
10009 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010010}
10011
10012void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +000010013 VectorFormat vform = kFormatUndefined;
10014 unsigned zm_code = instr->GetRm() & 0xf;
10015 unsigned index = instr->ExtractBits(20, 19);
10016
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010017 switch (instr->Mask(SVEFPMulIndexMask)) {
10018 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010019 vform = kFormatVnD;
10020 index >>= 1; // Only bit 20 is the index for D lanes.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010021 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010022 case FMUL_z_zzi_h_i3h:
10023 index += 4; // Bit 22 (i3h) is the top bit of index.
10024 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010025 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010026 vform = kFormatVnH;
10027 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010028 break;
10029 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010030 vform = kFormatVnS;
10031 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010032 break;
10033 default:
10034 VIXL_UNIMPLEMENTED();
10035 break;
10036 }
Martyn Capewell50e9f552020-01-07 17:45:03 +000010037
10038 SimVRegister& zd = ReadVRegister(instr->GetRd());
10039 SimVRegister& zn = ReadVRegister(instr->GetRn());
10040 SimVRegister temp;
10041
Martyn Capewell46352612020-07-02 15:47:54 +010010042 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
Martyn Capewell50e9f552020-01-07 17:45:03 +000010043 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010044}
10045
10046void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -080010047 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongf8d29f12020-02-16 22:53:18 -080010048 SimVRegister& zd = ReadVRegister(instr->GetRd());
10049 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10050 SimVRegister result;
10051
Martyn Capewell310a0822020-09-08 20:09:17 +010010052 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10053
TatWai Chongf8d29f12020-02-16 22:53:18 -080010054 if (instr->ExtractBit(15) == 0) {
10055 // Floating-point multiply-accumulate writing addend.
10056 SimVRegister& zm = ReadVRegister(instr->GetRm());
10057 SimVRegister& zn = ReadVRegister(instr->GetRn());
10058
10059 switch (instr->Mask(SVEFPMulAddMask)) {
10060 // zda = zda + zn * zm
10061 case FMLA_z_p_zzz:
10062 fmla(vform, result, zd, zn, zm);
10063 break;
10064 // zda = -zda + -zn * zm
10065 case FNMLA_z_p_zzz:
10066 fneg(vform, result, zd);
10067 fmls(vform, result, result, zn, zm);
10068 break;
10069 // zda = zda + -zn * zm
10070 case FMLS_z_p_zzz:
10071 fmls(vform, result, zd, zn, zm);
10072 break;
10073 // zda = -zda + zn * zm
10074 case FNMLS_z_p_zzz:
10075 fneg(vform, result, zd);
10076 fmla(vform, result, result, zn, zm);
10077 break;
10078 default:
10079 VIXL_UNIMPLEMENTED();
10080 break;
10081 }
10082 } else {
10083 // Floating-point multiply-accumulate writing multiplicand.
10084 SimVRegister& za = ReadVRegister(instr->GetRm());
10085 SimVRegister& zm = ReadVRegister(instr->GetRn());
10086
10087 switch (instr->Mask(SVEFPMulAddMask)) {
10088 // zdn = za + zdn * zm
10089 case FMAD_z_p_zzz:
10090 fmla(vform, result, za, zd, zm);
10091 break;
10092 // zdn = -za + -zdn * zm
10093 case FNMAD_z_p_zzz:
10094 fneg(vform, result, za);
10095 fmls(vform, result, result, zd, zm);
10096 break;
10097 // zdn = za + -zdn * zm
10098 case FMSB_z_p_zzz:
10099 fmls(vform, result, za, zd, zm);
10100 break;
10101 // zdn = -za + zdn * zm
10102 case FNMSB_z_p_zzz:
10103 fneg(vform, result, za);
10104 fmla(vform, result, result, zd, zm);
10105 break;
10106 default:
10107 VIXL_UNIMPLEMENTED();
10108 break;
10109 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010110 }
TatWai Chongf8d29f12020-02-16 22:53:18 -080010111
10112 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010113}
10114
10115void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010116 VectorFormat vform = kFormatUndefined;
10117 unsigned zm_code = 0xffffffff;
10118 unsigned index = 0xffffffff;
10119
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010120 switch (instr->Mask(SVEFPMulAddIndexMask)) {
10121 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010122 case FMLS_z_zzzi_d:
10123 vform = kFormatVnD;
10124 zm_code = instr->GetRmLow16();
10125 // Only bit 20 is the index for D lanes.
10126 index = instr->ExtractBit(20);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010127 break;
10128 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010129 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010130 vform = kFormatVnS;
10131 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
10132 index = instr->ExtractBits(20, 19);
10133 break;
10134 case FMLA_z_zzzi_h:
10135 case FMLS_z_zzzi_h:
10136 case FMLA_z_zzzi_h_i3h:
10137 case FMLS_z_zzzi_h_i3h:
10138 vform = kFormatVnH;
10139 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
10140 index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010141 break;
10142 default:
10143 VIXL_UNIMPLEMENTED();
10144 break;
10145 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010146
10147 SimVRegister& zd = ReadVRegister(instr->GetRd());
10148 SimVRegister& zn = ReadVRegister(instr->GetRn());
10149 SimVRegister temp;
10150
Martyn Capewellc7501512020-03-16 10:35:33 +000010151 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010152 if (instr->ExtractBit(10) == 1) {
10153 fmls(vform, zd, zd, zn, temp);
10154 } else {
10155 fmla(vform, zd, zd, zn, temp);
10156 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010157}
10158
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010159void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -080010160 SimVRegister& zd = ReadVRegister(instr->GetRd());
10161 SimVRegister& zn = ReadVRegister(instr->GetRn());
10162 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10163 int dst_data_size;
10164 int src_data_size;
10165
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010166 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010167 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010168 case FCVTZU_z_p_z_d2w:
10169 dst_data_size = kSRegSize;
10170 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010171 break;
10172 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010173 case FCVTZU_z_p_z_d2x:
10174 dst_data_size = kDRegSize;
10175 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010176 break;
10177 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010178 case FCVTZU_z_p_z_fp162h:
10179 dst_data_size = kHRegSize;
10180 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010181 break;
10182 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010183 case FCVTZU_z_p_z_fp162w:
10184 dst_data_size = kSRegSize;
10185 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010186 break;
10187 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010188 case FCVTZU_z_p_z_fp162x:
10189 dst_data_size = kDRegSize;
10190 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010191 break;
10192 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010193 case FCVTZU_z_p_z_s2w:
10194 dst_data_size = kSRegSize;
10195 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010196 break;
10197 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010198 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010199 dst_data_size = kDRegSize;
10200 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010201 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010202 default:
10203 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -080010204 dst_data_size = 0;
10205 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010206 break;
10207 }
TatWai Chongdb7437c2020-01-09 17:44:10 -080010208
10209 VectorFormat vform =
10210 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -080010211
10212 if (instr->ExtractBit(16) == 0) {
10213 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10214 } else {
10215 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10216 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010217}
10218
10219void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -080010220 SimVRegister& zd = ReadVRegister(instr->GetRd());
10221 SimVRegister& zn = ReadVRegister(instr->GetRn());
10222 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10223 int dst_data_size;
10224 int src_data_size;
10225
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010226 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010227 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010228 dst_data_size = kHRegSize;
10229 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010230 break;
10231 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010232 dst_data_size = kSRegSize;
10233 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010234 break;
10235 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010236 dst_data_size = kDRegSize;
10237 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010238 break;
10239 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010240 dst_data_size = kSRegSize;
10241 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010242 break;
10243 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010244 dst_data_size = kDRegSize;
10245 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010246 break;
10247 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010248 dst_data_size = kHRegSize;
10249 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010250 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010251 default:
10252 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -080010253 dst_data_size = 0;
10254 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010255 break;
10256 }
TatWai Chong2cb1b612020-03-04 23:51:21 -080010257 VectorFormat vform =
10258 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10259
10260 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010261}
10262
10263void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010264 SimVRegister& zd = ReadVRegister(instr->GetRd());
10265 SimVRegister& zn = ReadVRegister(instr->GetRn());
10266 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10267 VectorFormat vform = instr->GetSVEVectorFormat();
10268 SimVRegister result;
10269
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010270 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010271 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010272 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010273 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010274 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -080010275 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010276 break;
10277 default:
10278 VIXL_UNIMPLEMENTED();
10279 break;
10280 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010281 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010282}
10283
10284void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010285 SimVRegister& zd = ReadVRegister(instr->GetRd());
10286 SimVRegister& zn = ReadVRegister(instr->GetRn());
10287 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10288 VectorFormat vform = instr->GetSVEVectorFormat();
10289 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10290 bool exact_exception = false;
10291
Martyn Capewell310a0822020-09-08 20:09:17 +010010292 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10293
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010294 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010295 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010296 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010297 break;
10298 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010299 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010300 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010301 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010302 break;
10303 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010304 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010305 break;
10306 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010307 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010308 break;
10309 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010310 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010311 break;
10312 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010313 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010314 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010315 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010316 VIXL_UNIMPLEMENTED();
10317 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010318 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010319
10320 SimVRegister result;
10321 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10322 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010323}
10324
10325void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -080010326 SimVRegister& zd = ReadVRegister(instr->GetRd());
10327 SimVRegister& zn = ReadVRegister(instr->GetRn());
10328 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10329 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10330 int dst_data_size;
10331 int src_data_size;
10332
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010333 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010334 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010335 case UCVTF_z_p_z_h2fp16:
10336 dst_data_size = kHRegSize;
10337 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010338 break;
10339 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010340 case UCVTF_z_p_z_w2d:
10341 dst_data_size = kDRegSize;
10342 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010343 break;
10344 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010345 case UCVTF_z_p_z_w2fp16:
10346 dst_data_size = kHRegSize;
10347 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010348 break;
10349 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010350 case UCVTF_z_p_z_w2s:
10351 dst_data_size = kSRegSize;
10352 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010353 break;
10354 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010355 case UCVTF_z_p_z_x2d:
10356 dst_data_size = kDRegSize;
10357 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010358 break;
10359 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010360 case UCVTF_z_p_z_x2fp16:
10361 dst_data_size = kHRegSize;
10362 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010363 break;
10364 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010365 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010366 dst_data_size = kSRegSize;
10367 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010368 break;
10369 default:
10370 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -080010371 dst_data_size = 0;
10372 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010373 break;
10374 }
TatWai Chong31cd6a02020-01-10 13:03:26 -080010375
10376 VectorFormat vform =
10377 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10378
10379 if (instr->ExtractBit(16) == 0) {
10380 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10381 } else {
10382 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10383 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010384}
10385
10386void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +000010387 VectorFormat vform = instr->GetSVEVectorFormat();
10388 SimVRegister& zd = ReadVRegister(instr->GetRd());
10389 SimVRegister& zn = ReadVRegister(instr->GetRn());
10390 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10391
Martyn Capewell310a0822020-09-08 20:09:17 +010010392 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10393
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010394 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10395 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010396 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010397 break;
10398 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010399 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010400 break;
10401 default:
10402 VIXL_UNIMPLEMENTED();
10403 break;
10404 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010405}
10406
10407void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010408 VectorFormat vform = instr->GetSVEVectorFormat();
10409 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10410
10411 int count = CountActiveLanes(vform, pg);
10412
10413 if (instr->ExtractBit(11) == 0) {
10414 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10415 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10416 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010417 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010418 break;
10419 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010420 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010421 break;
10422 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010423 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010424 break;
10425 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010426 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010427 break;
10428 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010429 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010430 break;
10431 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010432 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010433 break;
10434 default:
10435 VIXL_UNIMPLEMENTED();
10436 break;
10437 }
10438 } else {
10439 bool is_saturating = (instr->ExtractBit(18) == 0);
10440 bool decrement =
10441 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10442 bool is_signed = (instr->ExtractBit(16) == 0);
10443 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10444 unsigned width = sf ? kXRegSize : kWRegSize;
10445
10446 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10447 case DECP_r_p_r:
10448 case INCP_r_p_r:
10449 case SQDECP_r_p_r_sx:
10450 case SQDECP_r_p_r_x:
10451 case SQINCP_r_p_r_sx:
10452 case SQINCP_r_p_r_x:
10453 case UQDECP_r_p_r_uw:
10454 case UQDECP_r_p_r_x:
10455 case UQINCP_r_p_r_uw:
10456 case UQINCP_r_p_r_x:
10457 WriteXRegister(instr->GetRd(),
10458 IncDecN(ReadXRegister(instr->GetRd()),
10459 decrement ? -count : count,
10460 width,
10461 is_saturating,
10462 is_signed));
10463 break;
10464 default:
10465 VIXL_UNIMPLEMENTED();
10466 break;
10467 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010468 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010469}
10470
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010471uint64_t Simulator::IncDecN(uint64_t acc,
10472 int64_t delta,
10473 unsigned n,
10474 bool is_saturating,
10475 bool is_signed) {
10476 VIXL_ASSERT(n <= 64);
10477 VIXL_ASSERT(IsIntN(n, delta));
10478
10479 uint64_t sign_mask = UINT64_C(1) << (n - 1);
10480 uint64_t mask = GetUintMask(n);
10481
10482 acc &= mask; // Ignore initial accumulator high bits.
10483 uint64_t result = (acc + delta) & mask;
10484
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010485 bool result_negative = ((result & sign_mask) != 0);
10486
10487 if (is_saturating) {
10488 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +000010489 bool acc_negative = ((acc & sign_mask) != 0);
10490 bool delta_negative = delta < 0;
10491
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010492 // If the signs of the operands are the same, but different from the
10493 // result, there was an overflow.
10494 if ((acc_negative == delta_negative) &&
10495 (acc_negative != result_negative)) {
10496 if (result_negative) {
10497 // Saturate to [..., INT<n>_MAX].
10498 result_negative = false;
10499 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
10500 } else {
10501 // Saturate to [INT<n>_MIN, ...].
10502 result_negative = true;
10503 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
10504 }
10505 }
10506 } else {
10507 if ((delta < 0) && (result > acc)) {
10508 // Saturate to [0, ...].
10509 result = 0;
10510 } else if ((delta > 0) && (result < acc)) {
10511 // Saturate to [..., UINT<n>_MAX].
10512 result = mask;
10513 }
10514 }
10515 }
10516
10517 // Sign-extend if necessary.
10518 if (result_negative && is_signed) result |= ~mask;
10519
10520 return result;
10521}
10522
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010523void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010524 VectorFormat vform = instr->GetSVEVectorFormat();
10525 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010526 switch (instr->Mask(SVEIndexGenerationMask)) {
10527 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010528 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010529 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010530 case INDEX_z_rr: {
10531 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10532 : instr->ExtractSignedBits(9, 5);
10533 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10534 : instr->ExtractSignedBits(20, 16);
10535 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010536 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010537 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010538 default:
10539 VIXL_UNIMPLEMENTED();
10540 break;
10541 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010542}
10543
10544void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -070010545 VectorFormat vform = instr->GetSVEVectorFormat();
10546 SimVRegister& zd = ReadVRegister(instr->GetRd());
10547 SimVRegister& zn = ReadVRegister(instr->GetRn());
10548 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010549 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10550 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010551 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010552 break;
10553 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010554 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010555 break;
10556 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010557 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010558 break;
10559 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010560 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010561 break;
10562 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010563 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010564 break;
10565 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010566 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010567 break;
10568 default:
10569 VIXL_UNIMPLEMENTED();
10570 break;
10571 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010572}
10573
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010574void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010575 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -070010576 VectorFormat vform = instr->GetSVEVectorFormat();
10577 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10578 SimVRegister& zm = ReadVRegister(instr->GetRn());
10579 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10580 SimVRegister result;
10581
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010582 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010583 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010584 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010585 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010586 case SUBR_z_p_zz:
10587 sub(vform, result, zm, zdn);
10588 break;
10589 case SUB_z_p_zz:
10590 sub(vform, result, zdn, zm);
10591 break;
10592 default:
10593 VIXL_UNIMPLEMENTED();
10594 break;
10595 }
10596 mov_merging(vform, zdn, pg, result);
10597}
10598
10599void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10600 VectorFormat vform = instr->GetSVEVectorFormat();
10601 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10602 SimVRegister& zm = ReadVRegister(instr->GetRn());
10603 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10604 SimVRegister result;
10605
10606 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010607 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010608 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010609 break;
10610 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010611 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010612 break;
10613 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010614 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010615 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010616 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010617 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010618 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010619 default:
10620 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010621 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010622 }
10623 mov_merging(vform, zdn, pg, result);
10624}
10625
10626void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10627 VectorFormat vform = instr->GetSVEVectorFormat();
10628 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10629 SimVRegister& zm = ReadVRegister(instr->GetRn());
10630 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10631 SimVRegister result;
10632
10633 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10634 case MUL_z_p_zz:
10635 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010636 break;
10637 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010638 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010639 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010640 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010641 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010642 break;
10643 default:
10644 VIXL_UNIMPLEMENTED();
10645 break;
10646 }
TatWai Chong13634762019-07-16 16:20:45 -070010647 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010648}
10649
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010650void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10651 const Instruction* instr) {
10652 VectorFormat vform = instr->GetSVEVectorFormat();
10653 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10654 SimVRegister& zm = ReadVRegister(instr->GetRn());
10655 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10656 SimVRegister result;
10657
10658 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10659 case SABD_z_p_zz:
10660 absdiff(vform, result, zdn, zm, true);
10661 break;
10662 case SMAX_z_p_zz:
10663 smax(vform, result, zdn, zm);
10664 break;
10665 case SMIN_z_p_zz:
10666 smin(vform, result, zdn, zm);
10667 break;
10668 case UABD_z_p_zz:
10669 absdiff(vform, result, zdn, zm, false);
10670 break;
10671 case UMAX_z_p_zz:
10672 umax(vform, result, zdn, zm);
10673 break;
10674 case UMIN_z_p_zz:
10675 umin(vform, result, zdn, zm);
10676 break;
10677 default:
10678 VIXL_UNIMPLEMENTED();
10679 break;
10680 }
10681 mov_merging(vform, zdn, pg, result);
10682}
10683
10684void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10685 VectorFormat vform = instr->GetSVEVectorFormat();
10686 SimVRegister& zd = ReadVRegister(instr->GetRd());
10687 SimVRegister scratch;
10688
10689 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10690 case MUL_z_zi:
10691 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10692 mul(vform, zd, zd, scratch);
10693 break;
10694 default:
10695 VIXL_UNIMPLEMENTED();
10696 break;
10697 }
10698}
10699
10700void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10701 VectorFormat vform = instr->GetSVEVectorFormat();
10702 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10703 SimVRegister& zm = ReadVRegister(instr->GetRn());
10704 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10705 SimVRegister result;
10706
10707 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10708
10709 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10710 case SDIVR_z_p_zz:
10711 sdiv(vform, result, zm, zdn);
10712 break;
10713 case SDIV_z_p_zz:
10714 sdiv(vform, result, zdn, zm);
10715 break;
10716 case UDIVR_z_p_zz:
10717 udiv(vform, result, zm, zdn);
10718 break;
10719 case UDIV_z_p_zz:
10720 udiv(vform, result, zdn, zm);
10721 break;
10722 default:
10723 VIXL_UNIMPLEMENTED();
10724 break;
10725 }
10726 mov_merging(vform, zdn, pg, result);
10727}
10728
10729void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10730 VectorFormat vform = instr->GetSVEVectorFormat();
10731 SimVRegister& zd = ReadVRegister(instr->GetRd());
10732 SimVRegister scratch;
10733
10734 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10735 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10736
10737 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10738 case SMAX_z_zi:
10739 dup_immediate(vform, scratch, signed_imm);
10740 smax(vform, zd, zd, scratch);
10741 break;
10742 case SMIN_z_zi:
10743 dup_immediate(vform, scratch, signed_imm);
10744 smin(vform, zd, zd, scratch);
10745 break;
10746 case UMAX_z_zi:
10747 dup_immediate(vform, scratch, unsigned_imm);
10748 umax(vform, zd, zd, scratch);
10749 break;
10750 case UMIN_z_zi:
10751 dup_immediate(vform, scratch, unsigned_imm);
10752 umin(vform, zd, zd, scratch);
10753 break;
10754 default:
10755 VIXL_UNIMPLEMENTED();
10756 break;
10757 }
10758}
10759
10760void Simulator::VisitSVEIntCompareScalarCountAndLimit(
10761 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -070010762 unsigned rn_code = instr->GetRn();
10763 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010764 SimPRegister& pd = ReadPRegister(instr->GetPd());
10765 VectorFormat vform = instr->GetSVEVectorFormat();
10766 bool is_64_bit = instr->ExtractBit(12) == 1;
10767 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
10768 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -070010769
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010770 bool last = true;
10771 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
10772 bool cond = false;
10773 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
10774 case WHILELE_p_p_rr:
10775 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -070010776 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010777 case WHILELO_p_p_rr:
10778 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
10779 break;
10780 case WHILELS_p_p_rr:
10781 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
10782 break;
10783 case WHILELT_p_p_rr:
10784 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -070010785 break;
10786 default:
TatWai Chongc844bb22019-06-10 15:32:53 -070010787 VIXL_UNIMPLEMENTED();
10788 break;
10789 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010790 last = last && cond;
10791 LogicPRegister dst(pd);
10792 dst.SetActive(vform, lane, last);
10793 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010794 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010795
10796 PredTest(vform, GetPTrue(), pd);
10797 LogSystemRegister(NZCV);
10798}
10799
10800void Simulator::VisitSVEConditionallyTerminateScalars(
10801 const Instruction* instr) {
10802 unsigned rn_code = instr->GetRn();
10803 unsigned rm_code = instr->GetRm();
10804 bool is_64_bit = instr->ExtractBit(22) == 1;
10805 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
10806 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
10807 bool term;
10808 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
10809 case CTERMEQ_rr:
10810 term = src1 == src2;
10811 break;
10812 case CTERMNE_rr:
10813 term = src1 != src2;
10814 break;
10815 default:
10816 term = false;
10817 VIXL_UNIMPLEMENTED();
10818 break;
10819 }
10820 ReadNzcv().SetN(term ? 1 : 0);
10821 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -070010822 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010823}
10824
10825void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070010826 bool commute_inputs = false;
10827 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010828 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
10829 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010830 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010831 break;
10832 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010833 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010834 break;
10835 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010836 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010837 break;
10838 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010839 cond = ge;
10840 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010841 break;
10842 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010843 cond = gt;
10844 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010845 break;
10846 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010847 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010848 break;
10849 default:
TatWai Chong302729c2019-06-14 16:18:51 -070010850 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010851 VIXL_UNIMPLEMENTED();
10852 break;
10853 }
TatWai Chong302729c2019-06-14 16:18:51 -070010854
10855 VectorFormat vform = instr->GetSVEVectorFormat();
10856 SimVRegister src2;
10857 dup_immediate(vform,
10858 src2,
10859 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
10860 SVEIntCompareVectorsHelper(cond,
10861 vform,
10862 ReadPRegister(instr->GetPd()),
10863 ReadPRegister(instr->GetPgLow8()),
10864 commute_inputs ? src2
10865 : ReadVRegister(instr->GetRn()),
10866 commute_inputs ? ReadVRegister(instr->GetRn())
10867 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010868}
10869
10870void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070010871 bool commute_inputs = false;
10872 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010873 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
10874 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010875 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010876 break;
10877 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010878 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010879 break;
10880 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010881 cond = hi;
10882 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010883 break;
10884 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070010885 cond = hs;
10886 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010887 break;
10888 default:
TatWai Chong302729c2019-06-14 16:18:51 -070010889 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010890 VIXL_UNIMPLEMENTED();
10891 break;
10892 }
TatWai Chong302729c2019-06-14 16:18:51 -070010893
10894 VectorFormat vform = instr->GetSVEVectorFormat();
10895 SimVRegister src2;
10896 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
10897 SVEIntCompareVectorsHelper(cond,
10898 vform,
10899 ReadPRegister(instr->GetPd()),
10900 ReadPRegister(instr->GetPgLow8()),
10901 commute_inputs ? src2
10902 : ReadVRegister(instr->GetRn()),
10903 commute_inputs ? ReadVRegister(instr->GetRn())
10904 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010905}
10906
10907void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -070010908 Instr op = instr->Mask(SVEIntCompareVectorsMask);
10909 bool is_wide_elements = false;
10910 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010911 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -070010912 case CMPGE_p_p_zw:
10913 case CMPGT_p_p_zw:
10914 case CMPHI_p_p_zw:
10915 case CMPHS_p_p_zw:
10916 case CMPLE_p_p_zw:
10917 case CMPLO_p_p_zw:
10918 case CMPLS_p_p_zw:
10919 case CMPLT_p_p_zw:
10920 case CMPNE_p_p_zw:
10921 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010922 break;
TatWai Chong96713fe2019-06-04 16:39:37 -070010923 }
10924
TatWai Chong302729c2019-06-14 16:18:51 -070010925 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -070010926 switch (op) {
10927 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010928 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010929 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010930 break;
10931 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010932 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010933 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010934 break;
10935 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010936 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010937 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010938 break;
10939 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010940 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010941 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010942 break;
10943 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010944 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010945 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010946 break;
10947 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010948 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070010949 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -070010950 break;
10951 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070010952 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -070010953 break;
10954 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070010955 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -070010956 break;
10957 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070010958 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -070010959 break;
10960 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070010961 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010962 break;
10963 default:
10964 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -070010965 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010966 break;
10967 }
TatWai Chong96713fe2019-06-04 16:39:37 -070010968
TatWai Chong302729c2019-06-14 16:18:51 -070010969 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -070010970 instr->GetSVEVectorFormat(),
10971 ReadPRegister(instr->GetPd()),
10972 ReadPRegister(instr->GetPgLow8()),
10973 ReadVRegister(instr->GetRn()),
10974 ReadVRegister(instr->GetRm()),
10975 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010976}
10977
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010978void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000010979 VectorFormat vform = instr->GetSVEVectorFormat();
10980 SimVRegister& zd = ReadVRegister(instr->GetRd());
10981 SimVRegister& zn = ReadVRegister(instr->GetRn());
10982
10983 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
10984 (vform == kFormatVnD));
10985
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010986 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010987 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +000010988 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010989 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010990 default:
10991 VIXL_UNIMPLEMENTED();
10992 break;
10993 }
10994}
10995
10996void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000010997 VectorFormat vform = instr->GetSVEVectorFormat();
10998 SimVRegister& zd = ReadVRegister(instr->GetRd());
10999 SimVRegister& zn = ReadVRegister(instr->GetRn());
11000 SimVRegister& zm = ReadVRegister(instr->GetRm());
11001
11002 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11003 (vform == kFormatVnD));
11004
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011005 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011006 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +000011007 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011008 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011009 default:
11010 VIXL_UNIMPLEMENTED();
11011 break;
11012 }
11013}
11014
11015void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11016 const Instruction* instr) {
11017 SimVRegister& zd = ReadVRegister(instr->GetRd());
11018 SimVRegister& zn = ReadVRegister(instr->GetRn());
11019
11020 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011021 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011022 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11023 // Record the movprfx, so the next ExecuteInstruction() can check it.
11024 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011025 break;
11026 default:
11027 VIXL_UNIMPLEMENTED();
11028 break;
11029 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011030}
11031
11032void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +010011033 VectorFormat vform = instr->GetSVEVectorFormat();
11034
11035 SimVRegister& zd = ReadVRegister(instr->GetRd());
11036 SimVRegister& zm = ReadVRegister(instr->GetRm());
11037
11038 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011039 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011040 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011041 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011042 break;
11043 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011044 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011045 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011046 case MAD_z_p_zzz:
11047 // 'za' is encoded in 'Rn'.
11048 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011049 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011050 case MSB_z_p_zzz: {
11051 // 'za' is encoded in 'Rn'.
11052 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11053 break;
11054 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011055 default:
11056 VIXL_UNIMPLEMENTED();
11057 break;
11058 }
Jacob Bramley22023df2019-05-14 17:55:43 +010011059 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011060}
11061
11062void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011063 VectorFormat vform = instr->GetSVEVectorFormat();
11064 SimVRegister& zda = ReadVRegister(instr->GetRd());
11065 SimVRegister& zn = ReadVRegister(instr->GetRn());
11066 SimVRegister& zm = ReadVRegister(instr->GetRm());
11067
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011068 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
11069 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011070 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011071 break;
11072 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011073 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011074 break;
11075 default:
11076 VIXL_UNIMPLEMENTED();
11077 break;
11078 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011079}
11080
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011081void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011082 VectorFormat vform = instr->GetSVEVectorFormat();
11083 SimVRegister& zn = ReadVRegister(instr->GetRn());
11084 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11085 SimVRegister& zd = ReadVRegister(instr->GetRd());
11086
11087 switch (instr->Mask(SVEMovprfxMask)) {
11088 case MOVPRFX_z_p_z:
11089 if (instr->ExtractBit(16)) {
11090 mov_merging(vform, zd, pg, zn);
11091 } else {
11092 mov_zeroing(vform, zd, pg, zn);
11093 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011094
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011095 // Record the movprfx, so the next ExecuteInstruction() can check it.
11096 movprfx_ = instr;
11097 break;
11098 default:
11099 VIXL_UNIMPLEMENTED();
11100 break;
11101 }
11102}
11103
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011104void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011105 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +010011106 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011107 SimVRegister& zn = ReadVRegister(instr->GetRn());
11108 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11109
11110 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11111 switch (instr->Mask(SVEIntReductionLogicalMask)) {
11112 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011113 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011114 break;
11115 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011116 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011117 break;
11118 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011119 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011120 break;
11121 default:
11122 VIXL_UNIMPLEMENTED();
11123 break;
11124 }
11125 } else {
11126 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011127 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011128 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011129 break;
11130 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011131 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011132 break;
11133 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011134 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011135 break;
11136 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011137 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011138 break;
11139 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011140 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011141 break;
11142 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011143 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011144 break;
11145 default:
11146 VIXL_UNIMPLEMENTED();
11147 break;
11148 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011149 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011150}
11151
11152void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011153 VectorFormat vform = instr->GetSVEVectorFormat();
11154 SimVRegister& zn = ReadVRegister(instr->GetRn());
11155
11156 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011157 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11158 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011159 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011160 break;
11161 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011162 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011163 break;
11164 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011165 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011166 break;
11167 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011168 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011169 break;
11170 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011171 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011172 break;
11173 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011174 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011175 break;
11176 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011177 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011178 break;
11179 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011180 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011181 break;
11182 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011183 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011184 break;
11185 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011186 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011187 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011188 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011189 break;
11190 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011191 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011192 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011193 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011194 break;
11195 default:
11196 VIXL_UNIMPLEMENTED();
11197 break;
11198 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011199
11200 SimVRegister& zd = ReadVRegister(instr->GetRd());
11201 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11202 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011203}
11204
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011205void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011206 // There is only one instruction in this group.
11207 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11208
11209 VectorFormat vform = instr->GetSVEVectorFormat();
11210 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11211 SimVRegister& zd = ReadVRegister(instr->GetRd());
11212
Martyn Capewell310a0822020-09-08 20:09:17 +010011213 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11214
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011215 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011216 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011217 case FCPY_z_p_i: {
11218 int imm8 = instr->ExtractBits(12, 5);
11219 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11220 Instruction::Imm8ToFP64(imm8));
11221 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011222 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011223 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011224 default:
11225 VIXL_UNIMPLEMENTED();
11226 break;
11227 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011228 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011229}
11230
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011231void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11232 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +010011233 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010011234 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +010011235 SimVRegister scratch;
11236
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011237 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11238 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011239
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011240 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011241 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011242 add_uint(vform, zd, zd, imm);
11243 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011244 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011245 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11246 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011247 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011248 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11249 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011250 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011251 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +010011252 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011253 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011254 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011255 sub_uint(vform, zd, zd, imm);
11256 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011257 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011258 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11259 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011260 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011261 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11262 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011263 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011264 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011265 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011266}
TatWai Chong6995bfd2019-09-26 10:48:05 +010011267
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011268void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11269 SimVRegister& zd = ReadVRegister(instr->GetRd());
11270
Martyn Capewell8ed83522020-08-11 16:19:43 +010011271 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011272 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +010011273 int shift = instr->ExtractBit(13) * 8;
11274 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011275
11276 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11277 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +010011278 // The encoding of byte-sized lanes with lsl #8 is undefined.
11279 if ((format == kFormatVnB) && (shift == 8)) {
11280 VIXL_UNIMPLEMENTED();
11281 } else {
11282 dup_immediate(format, zd, imm);
11283 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011284 break;
11285 default:
11286 VIXL_UNIMPLEMENTED();
11287 break;
11288 }
11289}
11290
11291void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11292 VectorFormat vform = instr->GetSVEVectorFormat();
11293 SimVRegister& zd = ReadVRegister(instr->GetRd());
11294
11295 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011296 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +010011297 switch (vform) {
11298 case kFormatVnH:
11299 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11300 break;
11301 case kFormatVnS:
11302 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11303 break;
11304 case kFormatVnD:
11305 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11306 break;
11307 default:
11308 VIXL_UNIMPLEMENTED();
11309 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011310 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011311 default:
11312 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011313 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011314 }
11315}
11316
11317void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11318 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011319 switch (instr->Mask(
11320 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11321 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011322 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011323 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011324 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011325 break;
11326 default:
11327 VIXL_UNIMPLEMENTED();
11328 break;
11329 }
TatWai Chong113d9192020-05-19 01:02:36 -070011330
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011331 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11332 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011333}
11334
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011335void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011336 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011337 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11338 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011339 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011340 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011341 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011342 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011343 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011344 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011345 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011346 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011347 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011348 break;
11349 default:
11350 VIXL_UNIMPLEMENTED();
11351 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011352 }
TatWai Chong113d9192020-05-19 01:02:36 -070011353
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011354 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11355 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011356}
11357
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011358void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11359 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011360 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11361 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011362 VIXL_UNIMPLEMENTED();
11363 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011364 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011365 VIXL_UNIMPLEMENTED();
11366 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011367 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011368 VIXL_UNIMPLEMENTED();
11369 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011370 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011371 VIXL_UNIMPLEMENTED();
11372 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011373 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011374 VIXL_UNIMPLEMENTED();
11375 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011376 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011377 VIXL_UNIMPLEMENTED();
11378 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011379 case LDFF1H_z_p_ai_s:
11380 VIXL_UNIMPLEMENTED();
11381 break;
11382 case LDFF1SB_z_p_ai_s:
11383 VIXL_UNIMPLEMENTED();
11384 break;
11385 case LDFF1SH_z_p_ai_s:
11386 VIXL_UNIMPLEMENTED();
11387 break;
11388 case LDFF1W_z_p_ai_s:
11389 VIXL_UNIMPLEMENTED();
11390 break;
11391 default:
11392 VIXL_UNIMPLEMENTED();
11393 break;
11394 }
11395}
11396
11397void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11398 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011399 switch (
11400 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11401 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011402 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011403 break;
11404 default:
11405 VIXL_UNIMPLEMENTED();
11406 break;
11407 }
TatWai Chong113d9192020-05-19 01:02:36 -070011408
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011409 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11410 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011411}
11412
11413void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11414 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011415 switch (
11416 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011417 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011418 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011419 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011420 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011421 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011422 break;
11423 default:
11424 VIXL_UNIMPLEMENTED();
11425 break;
11426 }
11427}
11428
11429void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11430 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011431 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011432 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011433 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011434 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011435 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011436 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011437 break;
11438 default:
11439 VIXL_UNIMPLEMENTED();
11440 break;
11441 }
11442}
11443
11444void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11445 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011446 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011447 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011448 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011449 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011450 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011451 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011452 break;
11453 default:
11454 VIXL_UNIMPLEMENTED();
11455 break;
11456 }
11457}
11458
11459void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11460 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011461 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011462 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011463 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011464 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011465 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011466 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +010011467 if (instr->GetRm() == kZeroRegCode) {
11468 VIXL_UNIMPLEMENTED();
11469 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011470 break;
11471 default:
11472 VIXL_UNIMPLEMENTED();
11473 break;
11474 }
11475}
11476
11477void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -070011478 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011479 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011480 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -070011481 case LD1RB_z_p_bi_u16:
11482 case LD1RB_z_p_bi_u32:
11483 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011484 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011485 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011486 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -070011487 case LD1RW_z_p_bi_u32:
11488 case LD1RW_z_p_bi_u64:
11489 case LD1RD_z_p_bi_u64:
11490 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011491 break;
11492 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011493 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011494 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011495 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011496 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011497 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -070011498 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011499 break;
11500 default:
TatWai Chong85e15102020-05-04 21:00:40 -070011501 // This encoding group is complete, so no other values should be possible.
11502 VIXL_UNREACHABLE();
11503 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011504 break;
11505 }
TatWai Chong85e15102020-05-04 21:00:40 -070011506
11507 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11508 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11509 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11510 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11511 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11512 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11513 VectorFormat unpack_vform =
11514 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11515 SimVRegister temp;
11516 ld1r(vform, unpack_vform, temp, base, is_signed);
11517 mov_zeroing(vform,
11518 ReadVRegister(instr->GetRt()),
11519 ReadPRegister(instr->GetPgLow8()),
11520 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011521}
11522
11523void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11524 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11525 case LDR_p_bi: {
11526 SimPRegister& pt = ReadPRegister(instr->GetPt());
11527 int pl = GetPredicateLengthInBytes();
11528 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11529 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11530 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11531 for (int i = 0; i < pl; i++) {
11532 pt.Insert(i, Memory::Read<uint8_t>(address + i));
11533 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011534 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011535 break;
11536 }
11537 default:
11538 VIXL_UNIMPLEMENTED();
11539 break;
11540 }
11541}
11542
11543void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011544 switch (instr->Mask(SVELoadVectorRegisterMask)) {
11545 case LDR_z_bi: {
11546 SimVRegister& zt = ReadVRegister(instr->GetRt());
11547 int vl = GetVectorLengthInBytes();
11548 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11549 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11550 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11551 for (int i = 0; i < vl; i++) {
11552 zt.Insert(i, Memory::Read<uint8_t>(address + i));
11553 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011554 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011555 break;
11556 }
11557 default:
11558 VIXL_UNIMPLEMENTED();
11559 break;
11560 }
11561}
11562
11563void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11564 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011565 switch (instr->Mask(
11566 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011567 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011568 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011569 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011570 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011571 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011572 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011573 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011574 case LDFF1D_z_p_bz_d_x32_scaled:
11575 case LDFF1SH_z_p_bz_d_x32_scaled:
11576 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011577 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011578 default:
11579 VIXL_UNIMPLEMENTED();
11580 break;
11581 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011582
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011583 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11584 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011585}
11586
11587void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11588 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011589 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11590 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011591 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011592 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011593 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011594 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011595 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011596 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011597 case LDFF1D_z_p_bz_d_64_scaled:
11598 case LDFF1SH_z_p_bz_d_64_scaled:
11599 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011600 break;
11601 default:
11602 VIXL_UNIMPLEMENTED();
11603 break;
11604 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011605
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011606 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011607}
11608
11609void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11610 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011611 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11612 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011613 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011614 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011615 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011616 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011617 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011618 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011619 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011620 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011621 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011622 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011623 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011624 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011625 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011626 break;
11627 default:
11628 VIXL_UNIMPLEMENTED();
11629 break;
11630 }
TatWai Chong113d9192020-05-19 01:02:36 -070011631
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011632 SVEGatherLoadScalarPlusVectorHelper(instr,
11633 kFormatVnD,
11634 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011635}
11636
11637void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11638 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011639 switch (instr->Mask(
11640 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11641 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011642 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011643 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011644 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011645 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011646 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011647 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011648 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011649 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011650 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011651 case LDFF1D_z_p_bz_d_x32_unscaled:
11652 case LDFF1SB_z_p_bz_d_x32_unscaled:
11653 case LDFF1SH_z_p_bz_d_x32_unscaled:
11654 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011655 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011656 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011657 VIXL_UNIMPLEMENTED();
11658 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011659 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011660
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011661 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11662 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011663}
11664
11665void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11666 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011667 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11668 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011669 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011670 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011671 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011672 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011673 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011674 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011675 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011676 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011677 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011678 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011679 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011680 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011681 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011682 break;
11683 default:
11684 VIXL_UNIMPLEMENTED();
11685 break;
11686 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +000011687 bool is_signed = instr->ExtractBit(14) == 0;
11688 bool is_ff = instr->ExtractBit(13) == 1;
11689 // Note that these instructions don't use the Dtype encoding.
11690 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11691 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11692 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11693 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11694 if (is_ff) {
11695 VIXL_UNIMPLEMENTED();
11696 } else {
11697 SVEStructuredLoadHelper(kFormatVnD,
11698 ReadPRegister(instr->GetPgLow8()),
11699 instr->GetRt(),
11700 addr,
11701 is_signed);
11702 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011703}
11704
11705void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11706 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011707 switch (
11708 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011709 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011710 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011711 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011712 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011713 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011714 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011715 default:
11716 VIXL_UNIMPLEMENTED();
11717 break;
11718 }
11719}
11720
11721void Simulator::
11722 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
11723 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011724 switch (instr->Mask(
11725 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011726 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011727 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011728 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011729 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011730 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011731 break;
11732 default:
11733 VIXL_UNIMPLEMENTED();
11734 break;
11735 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011736}
11737
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011738void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
11739 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011740 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011741 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011742 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011743 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011744 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011745 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011746 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011747 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011748 VIXL_UNIMPLEMENTED();
11749 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011750 }
11751}
11752
11753void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
11754 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +000011755 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +000011756 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011757 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011758 case LDFF1B_z_p_br_u16:
11759 case LDFF1B_z_p_br_u32:
11760 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011761 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011762 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011763 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011764 case LDFF1W_z_p_br_u32:
11765 case LDFF1W_z_p_br_u64:
11766 case LDFF1D_z_p_br_u64:
11767 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011768 break;
11769 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011770 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011771 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011772 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011773 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011774 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011775 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011776 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011777 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011778 // This encoding group is complete, so no other values should be possible.
11779 VIXL_UNREACHABLE();
11780 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011781 break;
11782 }
Jacob Bramley85a9c102019-12-09 17:48:29 +000011783
11784 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11785 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11786 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11787 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11788 uint64_t offset = ReadXRegister(instr->GetRm());
11789 offset <<= msize_in_bytes_log2;
11790 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11791 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11792 SVEFaultTolerantLoadHelper(vform,
11793 ReadPRegister(instr->GetPgLow8()),
11794 instr->GetRt(),
11795 addr,
11796 kSVEFirstFaultLoad,
11797 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011798}
11799
11800void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
11801 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011802 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011803 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011804 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011805 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011806 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011807 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011808 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011809 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011810 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011811 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011812 case LDNF1W_z_p_bi_u32:
11813 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011814 break;
11815 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011816 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011817 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011818 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011819 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011820 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011821 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011822 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011823 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011824 VIXL_UNIMPLEMENTED();
11825 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011826 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011827 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11828 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11829 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11830 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11831 int vl = GetVectorLengthInBytes();
11832 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11833 uint64_t offset =
11834 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
11835 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11836 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11837 SVEFaultTolerantLoadHelper(vform,
11838 ReadPRegister(instr->GetPgLow8()),
11839 instr->GetRt(),
11840 addr,
11841 kSVENonFaultLoad,
11842 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011843}
11844
11845void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
11846 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000011847 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11848 VectorFormat vform = kFormatUndefined;
11849
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011850 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
11851 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011852 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011853 break;
11854 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011855 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011856 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011857 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011858 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011859 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011860 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011861 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011862 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011863 default:
11864 VIXL_UNIMPLEMENTED();
11865 break;
11866 }
Martyn Capewell72765d12020-03-23 14:25:53 +000011867 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
11868 int vl = GetVectorLengthInBytes();
11869 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
11870 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11871 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11872 SVEStructuredLoadHelper(vform,
11873 pg,
11874 instr->GetRt(),
11875 addr,
11876 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011877}
11878
11879void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
11880 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000011881 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11882 VectorFormat vform = kFormatUndefined;
11883
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011884 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
11885 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011886 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011887 break;
11888 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011889 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011890 break;
11891 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011892 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011893 break;
11894 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000011895 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011896 break;
11897 default:
11898 VIXL_UNIMPLEMENTED();
11899 break;
11900 }
Martyn Capewell72765d12020-03-23 14:25:53 +000011901 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
11902 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
11903 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11904 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11905 SVEStructuredLoadHelper(vform,
11906 pg,
11907 instr->GetRt(),
11908 addr,
11909 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011910}
11911
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011912void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
11913 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011914 SimVRegister& zt = ReadVRegister(instr->GetRt());
11915 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11916
11917 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
11918 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
11919
11920 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011921 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
11922 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011923 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011924 break;
11925 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011926 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011927 break;
11928 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011929 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011930 break;
11931 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011932 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011933 break;
11934 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011935 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011936 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011937 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011938 ld1(kFormat16B, zt, addr + offset);
11939 mov_zeroing(vform, zt, pg, zt);
11940 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011941}
11942
11943void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
11944 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011945 SimVRegister& zt = ReadVRegister(instr->GetRt());
11946 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11947
11948 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
11949 uint64_t offset = ReadXRegister(instr->GetRm());
11950
11951 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011952 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
11953 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011954 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011955 break;
11956 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011957 vform = kFormatVnD;
11958 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011959 break;
11960 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011961 vform = kFormatVnH;
11962 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011963 break;
11964 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011965 vform = kFormatVnS;
11966 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011967 break;
11968 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011969 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011970 break;
11971 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000011972 ld1(kFormat16B, zt, addr + offset);
11973 mov_zeroing(vform, zt, pg, zt);
11974 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011975}
11976
11977void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
11978 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011979 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
11980 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011981 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011982 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011983 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011984 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011985 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011986 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011987 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011988 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011989 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011990 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000011991 case LD4W_z_p_bi_contiguous: {
11992 int vl = GetVectorLengthInBytes();
11993 int msz = instr->ExtractBits(24, 23);
11994 int reg_count = instr->ExtractBits(22, 21) + 1;
11995 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
11996 LogicSVEAddressVector addr(
11997 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
11998 addr.SetMsizeInBytesLog2(msz);
11999 addr.SetRegCount(reg_count);
12000 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12001 ReadPRegister(instr->GetPgLow8()),
12002 instr->GetRt(),
12003 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012004 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012005 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012006 default:
12007 VIXL_UNIMPLEMENTED();
12008 break;
12009 }
12010}
12011
12012void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12013 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012014 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12015 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012016 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012017 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012018 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012019 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012020 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012021 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012022 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012023 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012024 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012025 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000012026 case LD4W_z_p_br_contiguous: {
12027 int msz = instr->ExtractBits(24, 23);
12028 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12029 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12030 LogicSVEAddressVector addr(
12031 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12032 addr.SetMsizeInBytesLog2(msz);
12033 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12034 SVEStructuredLoadHelper(vform,
12035 ReadPRegister(instr->GetPgLow8()),
12036 instr->GetRt(),
12037 addr,
12038 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012039 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000012040 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012041 default:
12042 VIXL_UNIMPLEMENTED();
12043 break;
12044 }
12045}
12046
12047void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12048 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012049 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12050 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012051 case ST1W_z_p_bz_s_x32_scaled: {
12052 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12053 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12054 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12055 uint64_t base = ReadXRegister(instr->GetRn());
12056 SVEOffsetModifier mod =
12057 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12058 LogicSVEAddressVector addr(base,
12059 &ReadVRegister(instr->GetRm()),
12060 kFormatVnS,
12061 mod,
12062 scale);
12063 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12064 SVEStructuredStoreHelper(kFormatVnS,
12065 ReadPRegister(instr->GetPgLow8()),
12066 instr->GetRt(),
12067 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012068 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012069 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012070 default:
12071 VIXL_UNIMPLEMENTED();
12072 break;
12073 }
12074}
12075
12076void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12077 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012078 switch (
12079 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12080 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012081 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012082 case ST1W_z_p_bz_s_x32_unscaled: {
12083 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12084 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12085 uint64_t base = ReadXRegister(instr->GetRn());
12086 SVEOffsetModifier mod =
12087 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12088 LogicSVEAddressVector addr(base,
12089 &ReadVRegister(instr->GetRm()),
12090 kFormatVnS,
12091 mod);
12092 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12093 SVEStructuredStoreHelper(kFormatVnS,
12094 ReadPRegister(instr->GetPgLow8()),
12095 instr->GetRt(),
12096 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012097 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012098 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012099 default:
12100 VIXL_UNIMPLEMENTED();
12101 break;
12102 }
12103}
12104
12105void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12106 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012107 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012108 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12109 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012110 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012111 break;
12112 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012113 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012114 break;
12115 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012116 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012117 break;
12118 default:
12119 VIXL_UNIMPLEMENTED();
12120 break;
12121 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012122 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12123 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12124 addr.SetMsizeInBytesLog2(msz);
12125 SVEStructuredStoreHelper(kFormatVnS,
12126 ReadPRegister(instr->GetPgLow8()),
12127 instr->GetRt(),
12128 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012129}
12130
12131void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12132 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012133 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12134 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012135 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012136 case ST1W_z_p_bz_d_64_scaled: {
12137 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12138 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12139 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12140 uint64_t base = ReadXRegister(instr->GetRn());
12141 LogicSVEAddressVector addr(base,
12142 &ReadVRegister(instr->GetRm()),
12143 kFormatVnD,
12144 SVE_LSL,
12145 scale);
12146 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12147 SVEStructuredStoreHelper(kFormatVnD,
12148 ReadPRegister(instr->GetPgLow8()),
12149 instr->GetRt(),
12150 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012151 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012152 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012153 default:
12154 VIXL_UNIMPLEMENTED();
12155 break;
12156 }
12157}
12158
12159void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12160 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012161 switch (
12162 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12163 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012164 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012165 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012166 case ST1W_z_p_bz_d_64_unscaled: {
12167 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12168 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012169 uint64_t base = ReadXRegister(instr->GetRn());
12170 LogicSVEAddressVector addr(base,
12171 &ReadVRegister(instr->GetRm()),
12172 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070012173 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012174 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12175 SVEStructuredStoreHelper(kFormatVnD,
12176 ReadPRegister(instr->GetPgLow8()),
12177 instr->GetRt(),
12178 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012179 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012180 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012181 default:
12182 VIXL_UNIMPLEMENTED();
12183 break;
12184 }
12185}
12186
12187void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12188 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012189 switch (instr->Mask(
12190 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12191 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012192 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012193 case ST1W_z_p_bz_d_x32_scaled: {
12194 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12195 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12196 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12197 uint64_t base = ReadXRegister(instr->GetRn());
12198 SVEOffsetModifier mod =
12199 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12200 LogicSVEAddressVector addr(base,
12201 &ReadVRegister(instr->GetRm()),
12202 kFormatVnD,
12203 mod,
12204 scale);
12205 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12206 SVEStructuredStoreHelper(kFormatVnD,
12207 ReadPRegister(instr->GetPgLow8()),
12208 instr->GetRt(),
12209 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012210 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012211 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012212 default:
12213 VIXL_UNIMPLEMENTED();
12214 break;
12215 }
12216}
12217
12218void Simulator::
12219 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12220 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012221 switch (instr->Mask(
12222 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12223 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012224 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012225 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012226 case ST1W_z_p_bz_d_x32_unscaled: {
12227 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12228 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12229 uint64_t base = ReadXRegister(instr->GetRn());
12230 SVEOffsetModifier mod =
12231 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12232 LogicSVEAddressVector addr(base,
12233 &ReadVRegister(instr->GetRm()),
12234 kFormatVnD,
12235 mod);
12236 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12237 SVEStructuredStoreHelper(kFormatVnD,
12238 ReadPRegister(instr->GetPgLow8()),
12239 instr->GetRt(),
12240 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012241 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012242 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012243 default:
12244 VIXL_UNIMPLEMENTED();
12245 break;
12246 }
12247}
12248
12249void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12250 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012251 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012252 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12253 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012254 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012255 break;
12256 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012257 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012258 break;
12259 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012260 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012261 break;
12262 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012263 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012264 break;
12265 default:
12266 VIXL_UNIMPLEMENTED();
12267 break;
12268 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012269 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12270 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12271 addr.SetMsizeInBytesLog2(msz);
12272 SVEStructuredStoreHelper(kFormatVnD,
12273 ReadPRegister(instr->GetPgLow8()),
12274 instr->GetRt(),
12275 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012276}
12277
12278void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12279 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012280 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12281 VectorFormat vform = kFormatUndefined;
12282
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012283 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12284 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012285 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012286 break;
12287 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012288 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012289 break;
12290 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012291 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012292 break;
12293 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012294 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012295 break;
12296 default:
12297 VIXL_UNIMPLEMENTED();
12298 break;
12299 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012300 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12301 int vl = GetVectorLengthInBytes();
12302 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12303 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12304 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12305 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012306}
12307
12308void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12309 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012310 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12311 VectorFormat vform = kFormatUndefined;
12312
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012313 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12314 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012315 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012316 break;
12317 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012318 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012319 break;
12320 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012321 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012322 break;
12323 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012324 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012325 break;
12326 default:
12327 VIXL_UNIMPLEMENTED();
12328 break;
12329 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012330 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12331 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12332 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12333 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12334 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012335}
12336
12337void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12338 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012339 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12340 case ST1B_z_p_bi:
12341 case ST1D_z_p_bi:
12342 case ST1H_z_p_bi:
12343 case ST1W_z_p_bi: {
12344 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012345 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12346 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12347 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12348 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12349 uint64_t offset =
12350 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012351 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012352 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012353 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012354 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12355 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012356 ReadPRegister(instr->GetPgLow8()),
12357 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012358 addr);
12359 break;
12360 }
12361 default:
12362 VIXL_UNIMPLEMENTED();
12363 break;
12364 }
12365}
12366
12367void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12368 const Instruction* instr) {
12369 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12370 case ST1B_z_p_br:
12371 case ST1D_z_p_br:
12372 case ST1H_z_p_br:
12373 case ST1W_z_p_br: {
12374 uint64_t offset = ReadXRegister(instr->GetRm());
12375 offset <<= instr->ExtractBits(24, 23);
12376 VectorFormat vform =
12377 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12378 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012379 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12380 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012381 ReadPRegister(instr->GetPgLow8()),
12382 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012383 addr);
12384 break;
12385 }
12386 default:
12387 VIXL_UNIMPLEMENTED();
12388 break;
12389 }
12390}
12391
12392void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12393 const Instruction* instr) {
12394 VectorFormat vform = instr->GetSVEVectorFormat();
12395 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12396 SimVRegister z_result;
12397
12398 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12399 case CPY_z_p_v:
12400 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12401 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12402 break;
12403 default:
12404 VIXL_UNIMPLEMENTED();
12405 break;
12406 }
12407}
12408
12409void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12410 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012411 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12412 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012413 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012414 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012415 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012416 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012417 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012418 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012419 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012420 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012421 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012422 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012423 case ST4W_z_p_bi_contiguous: {
12424 int vl = GetVectorLengthInBytes();
12425 int msz = instr->ExtractBits(24, 23);
12426 int reg_count = instr->ExtractBits(22, 21) + 1;
12427 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12428 LogicSVEAddressVector addr(
12429 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12430 addr.SetMsizeInBytesLog2(msz);
12431 addr.SetRegCount(reg_count);
12432 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12433 ReadPRegister(instr->GetPgLow8()),
12434 instr->GetRt(),
12435 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012436 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012437 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012438 default:
12439 VIXL_UNIMPLEMENTED();
12440 break;
12441 }
12442}
12443
12444void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12445 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012446 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12447 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012448 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012449 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012450 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012451 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012452 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012453 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012454 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012455 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012456 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012457 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012458 case ST4W_z_p_br_contiguous: {
12459 int msz = instr->ExtractBits(24, 23);
12460 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12461 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12462 LogicSVEAddressVector addr(
12463 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12464 addr.SetMsizeInBytesLog2(msz);
12465 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12466 SVEStructuredStoreHelper(vform,
12467 ReadPRegister(instr->GetPgLow8()),
12468 instr->GetRt(),
12469 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012470 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012471 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012472 default:
12473 VIXL_UNIMPLEMENTED();
12474 break;
12475 }
12476}
12477
12478void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12479 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12480 case STR_p_bi: {
12481 SimPRegister& pt = ReadPRegister(instr->GetPt());
12482 int pl = GetPredicateLengthInBytes();
12483 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12484 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12485 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12486 for (int i = 0; i < pl; i++) {
12487 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
12488 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012489 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012490 break;
12491 }
12492 default:
12493 VIXL_UNIMPLEMENTED();
12494 break;
12495 }
12496}
12497
12498void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12499 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12500 case STR_z_bi: {
12501 SimVRegister& zt = ReadVRegister(instr->GetRt());
12502 int vl = GetVectorLengthInBytes();
12503 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12504 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12505 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12506 for (int i = 0; i < vl; i++) {
12507 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
12508 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012509 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012510 break;
12511 }
12512 default:
12513 VIXL_UNIMPLEMENTED();
12514 break;
12515 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012516}
12517
12518void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012519 VectorFormat vform = instr->GetSVEVectorFormat();
12520 SimVRegister& zda = ReadVRegister(instr->GetRd());
12521 SimVRegister& zn = ReadVRegister(instr->GetRn());
12522
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012523 switch (instr->Mask(SVEMulIndexMask)) {
12524 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012525 sdot(vform,
12526 zda,
12527 zn,
12528 ReadVRegister(instr->ExtractBits(19, 16)),
12529 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012530 break;
12531 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012532 sdot(vform,
12533 zda,
12534 zn,
12535 ReadVRegister(instr->ExtractBits(18, 16)),
12536 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012537 break;
12538 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012539 udot(vform,
12540 zda,
12541 zn,
12542 ReadVRegister(instr->ExtractBits(19, 16)),
12543 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012544 break;
12545 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012546 udot(vform,
12547 zda,
12548 zn,
12549 ReadVRegister(instr->ExtractBits(18, 16)),
12550 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012551 break;
12552 default:
12553 VIXL_UNIMPLEMENTED();
12554 break;
12555 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012556}
12557
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012558void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012559 SimPRegister& pd = ReadPRegister(instr->GetPd());
12560 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12561 SimPRegister& pn = ReadPRegister(instr->GetPn());
12562 SimPRegister result;
12563
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012564 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012565 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012566 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012567 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012568 break;
12569 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012570 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012571 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012572 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012573 default:
12574 VIXL_UNIMPLEMENTED();
12575 break;
12576 }
TatWai Chong5d872292020-01-02 15:39:51 -080012577
12578 if (instr->ExtractBit(4) == 1) {
12579 mov_merging(pd, pg, result);
12580 } else {
12581 mov_zeroing(pd, pg, result);
12582 }
12583
12584 // Set flag if needed.
12585 if (instr->ExtractBit(22) == 1) {
12586 PredTest(kFormatVnB, pg, pd);
12587 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012588}
12589
12590void Simulator::VisitSVEPropagateBreakToNextPartition(
12591 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012592 SimPRegister& pdm = ReadPRegister(instr->GetPd());
12593 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12594 SimPRegister& pn = ReadPRegister(instr->GetPn());
12595
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012596 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012597 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012598 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080012599 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012600 break;
12601 default:
12602 VIXL_UNIMPLEMENTED();
12603 break;
12604 }
TatWai Chong5d872292020-01-02 15:39:51 -080012605
12606 // Set flag if needed.
12607 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010012608 // Note that this ignores `pg`.
12609 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080012610 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012611}
12612
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012613void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012614 SimPRegister& pd = ReadPRegister(instr->GetPd());
12615 SimPRegister& pn = ReadPRegister(instr->GetPn());
12616
12617 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12618 SimVRegister zero;
12619 dup_immediate(kFormatVnB, zero, 0);
12620
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012621 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012622 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012623 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012624 break;
12625 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012626 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012627 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012628 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012629 VIXL_UNIMPLEMENTED();
12630 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012631 }
TatWai Chong47c26842020-02-10 01:51:32 -080012632 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012633}
12634
12635void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012636 VectorFormat vform = instr->GetSVEVectorFormat();
12637 SimPRegister& pd = ReadPRegister(instr->GetPd());
12638 SimPRegister& pn = ReadPRegister(instr->GetPn());
12639 SimPRegister& pm = ReadPRegister(instr->GetPm());
12640
12641 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12642 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12643
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012644 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012645 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012646 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012647 break;
12648 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012649 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012650 break;
12651 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012652 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012653 break;
12654 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012655 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012656 break;
12657 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012658 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012659 break;
12660 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012661 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012662 break;
12663 default:
12664 VIXL_UNIMPLEMENTED();
12665 break;
12666 }
TatWai Chong47c26842020-02-10 01:51:32 -080012667 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012668}
12669
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012670void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012671 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012672 case REV_p_p: {
12673 VectorFormat vform = instr->GetSVEVectorFormat();
12674 SimPRegister& pn = ReadPRegister(instr->GetPn());
12675 SimPRegister& pd = ReadPRegister(instr->GetPd());
12676 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12677 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080012678 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012679 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012680 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012681 default:
12682 VIXL_UNIMPLEMENTED();
12683 break;
12684 }
12685}
12686
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012687void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000012688 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12689 // Second source register "Zm" is encoded where "Zn" would usually be.
12690 SimVRegister& zm = ReadVRegister(instr->GetRn());
12691
12692 const int imm8h_mask = 0x001F0000;
12693 const int imm8l_mask = 0x00001C00;
12694 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
12695 int vl = GetVectorLengthInBytes();
12696 index = (index >= vl) ? 0 : index;
12697
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012698 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
12699 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000012700 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012701 break;
12702 default:
12703 VIXL_UNIMPLEMENTED();
12704 break;
12705 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012706}
12707
12708void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000012709 VectorFormat vform = instr->GetSVEVectorFormat();
12710 SimVRegister& zd = ReadVRegister(instr->GetRd());
12711 SimVRegister& zn = ReadVRegister(instr->GetRn());
12712 SimVRegister& zm = ReadVRegister(instr->GetRm());
12713
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012714 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
12715 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012716 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012717 break;
12718 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012719 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012720 break;
12721 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012722 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012723 break;
12724 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012725 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012726 break;
12727 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012728 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012729 break;
12730 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012731 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012732 break;
12733 default:
12734 VIXL_UNIMPLEMENTED();
12735 break;
12736 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012737}
12738
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012739void Simulator::VisitSVEConditionallyBroadcastElementToVector(
12740 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012741 VectorFormat vform = instr->GetSVEVectorFormat();
12742 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12743 SimVRegister& zm = ReadVRegister(instr->GetRn());
12744 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12745
12746 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012747 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012748 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012749 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012750 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012751 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012752 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012753 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012754 default:
12755 VIXL_UNIMPLEMENTED();
12756 break;
12757 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012758
12759 if (active_offset >= 0) {
12760 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12761 if (value.first) {
12762 dup_immediate(vform, zdn, value.second);
12763 } else {
12764 // Trigger a line of trace for the operation, even though it doesn't
12765 // change the register value.
12766 mov(vform, zdn, zdn);
12767 }
12768 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012769}
12770
12771void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
12772 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012773 VectorFormat vform = instr->GetSVEVectorFormat();
12774 SimVRegister& vdn = ReadVRegister(instr->GetRd());
12775 SimVRegister& zm = ReadVRegister(instr->GetRn());
12776 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12777
12778 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012779 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
12780 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012781 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012782 break;
12783 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012784 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012785 break;
12786 default:
12787 VIXL_UNIMPLEMENTED();
12788 break;
12789 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012790
12791 if (active_offset >= 0) {
12792 LogicVRegister dst(vdn);
12793 uint64_t src1_value = dst.Uint(vform, 0);
12794 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
12795 dup_immediate(vform, vdn, 0);
12796 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
12797 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012798}
12799
12800void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
12801 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012802 VectorFormat vform = instr->GetSVEVectorFormat();
12803 SimVRegister& zm = ReadVRegister(instr->GetRn());
12804 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12805
12806 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012807 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
12808 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012809 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012810 break;
12811 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012812 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012813 break;
12814 default:
12815 VIXL_UNIMPLEMENTED();
12816 break;
12817 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012818
12819 if (active_offset >= 0) {
12820 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12821 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
12822 GetUintMask(LaneSizeInBitsFromFormat(vform));
12823 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
12824 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012825}
12826
12827void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
12828 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012829 VectorFormat vform = instr->GetSVEVectorFormat();
12830 SimVRegister& vdn = ReadVRegister(instr->GetRd());
12831 SimVRegister& zm = ReadVRegister(instr->GetRn());
12832 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12833
12834 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012835 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
12836 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012837 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012838 break;
12839 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012840 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012841 break;
12842 default:
12843 VIXL_UNIMPLEMENTED();
12844 break;
12845 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012846
12847 if (active_offset >= 0) {
12848 LogicVRegister dst(vdn);
12849 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12850 dup_immediate(vform, vdn, 0);
12851 dst.SetUint(vform, 0, value.second);
12852 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012853}
12854
12855void Simulator::VisitSVEExtractElementToGeneralRegister(
12856 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012857 VectorFormat vform = instr->GetSVEVectorFormat();
12858 SimVRegister& zm = ReadVRegister(instr->GetRn());
12859 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12860
12861 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012862 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
12863 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012864 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012865 break;
12866 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012867 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012868 break;
12869 default:
12870 VIXL_UNIMPLEMENTED();
12871 break;
12872 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012873
12874 if (active_offset >= 0) {
12875 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12876 WriteXRegister(instr->GetRd(), value.second);
12877 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012878}
12879
12880void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012881 VectorFormat vform = instr->GetSVEVectorFormat();
12882 SimVRegister& zd = ReadVRegister(instr->GetRd());
12883 SimVRegister& zn = ReadVRegister(instr->GetRn());
12884 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12885
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012886 switch (instr->Mask(SVECompressActiveElementsMask)) {
12887 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012888 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012889 break;
12890 default:
12891 VIXL_UNIMPLEMENTED();
12892 break;
12893 }
12894}
12895
12896void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
12897 const Instruction* instr) {
12898 VectorFormat vform = instr->GetSVEVectorFormat();
12899 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12900 SimVRegister z_result;
12901
12902 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012903 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010012904 dup_immediate(vform,
12905 z_result,
12906 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
12907 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012908 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012909 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012910 VIXL_UNIMPLEMENTED();
12911 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012912 }
12913}
12914
12915void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010012916 VectorFormat vform = instr->GetSVEVectorFormat();
12917 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
12918 SimVRegister& zd = ReadVRegister(instr->GetRd());
12919
12920 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012921 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010012922 case CPY_z_p_i: {
12923 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
12924 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
12925 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012926 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010012927 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012928 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012929 VIXL_UNIMPLEMENTED();
12930 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012931 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010012932
12933 if (instr->ExtractBit(14) != 0) {
12934 mov_merging(vform, zd, pg, result);
12935 } else {
12936 mov_zeroing(vform, zd, pg, result);
12937 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012938}
12939
12940void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000012941 SimVRegister& zd = ReadVRegister(instr->GetRd());
12942 SimVRegister& zn = ReadVRegister(instr->GetRn());
12943 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12944 SimVRegister result;
12945
12946 // In NEON, the chunk size in which elements are REVersed is in the
12947 // instruction mnemonic, and the element size attached to the register.
12948 // SVE reverses the semantics; the mapping to logic functions below is to
12949 // account for this.
12950 VectorFormat chunk_form = instr->GetSVEVectorFormat();
12951 VectorFormat element_form = kFormatUndefined;
12952
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012953 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012954 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000012955 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012956 break;
12957 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000012958 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
12959 (chunk_form == kFormatVnD));
12960 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012961 break;
12962 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000012963 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
12964 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012965 break;
12966 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000012967 VIXL_ASSERT(chunk_form == kFormatVnD);
12968 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012969 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012970 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012971 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012972 break;
12973 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000012974
12975 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
12976 VIXL_ASSERT(element_form != kFormatUndefined);
12977 switch (chunk_form) {
12978 case kFormatVnH:
12979 rev16(element_form, result, zn);
12980 break;
12981 case kFormatVnS:
12982 rev32(element_form, result, zn);
12983 break;
12984 case kFormatVnD:
12985 rev64(element_form, result, zn);
12986 break;
12987 default:
12988 VIXL_UNIMPLEMENTED();
12989 }
12990 }
12991
12992 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012993}
12994
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012995void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012996 VectorFormat vform = instr->GetSVEVectorFormat();
12997 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12998 SimVRegister& zm = ReadVRegister(instr->GetRn());
12999 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13000
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013001 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
13002 case SPLICE_z_p_zz_des:
Martyn Capewellf804b602020-02-24 18:57:18 +000013003 splice(vform, zdn, pg, zdn, zm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013004 break;
13005 default:
13006 VIXL_UNIMPLEMENTED();
13007 break;
13008 }
13009}
TatWai Chong4f28df72019-08-14 17:50:30 -070013010
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013011void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13012 SimVRegister& zd = ReadVRegister(instr->GetRd());
13013 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13014 case DUP_z_r:
13015 dup_immediate(instr->GetSVEVectorFormat(),
13016 zd,
13017 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13018 break;
13019 default:
13020 VIXL_UNIMPLEMENTED();
13021 break;
13022 }
13023}
13024
13025void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13026 SimVRegister& zd = ReadVRegister(instr->GetRd());
13027 VectorFormat vform = instr->GetSVEVectorFormat();
13028 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13029 case INSR_z_v:
13030 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13031 break;
13032 default:
13033 VIXL_UNIMPLEMENTED();
13034 break;
13035 }
13036}
13037
13038void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13039 SimVRegister& zd = ReadVRegister(instr->GetRd());
13040 VectorFormat vform = instr->GetSVEVectorFormat();
13041 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13042 case INSR_z_r:
13043 insr(vform, zd, ReadXRegister(instr->GetRn()));
13044 break;
13045 default:
13046 VIXL_UNIMPLEMENTED();
13047 break;
13048 }
13049}
13050
13051void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13052 SimVRegister& zd = ReadVRegister(instr->GetRd());
13053 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070013054 case DUP_z_zi: {
13055 std::pair<int, int> index_and_lane_size =
13056 instr->GetSVEPermuteIndexAndLaneSizeLog2();
13057 int index = index_and_lane_size.first;
13058 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13059 VectorFormat vform =
13060 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13061 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13062 // Out of bounds, set the destination register to zero.
13063 dup_immediate(kFormatVnD, zd, 0);
13064 } else {
13065 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13066 }
13067 return;
13068 }
TatWai Chong4f28df72019-08-14 17:50:30 -070013069 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013070 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070013071 break;
13072 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013073}
TatWai Chong4f28df72019-08-14 17:50:30 -070013074
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013075void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13076 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070013077 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013078 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013079 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013080 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013081 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013082 default:
13083 VIXL_UNIMPLEMENTED();
13084 break;
13085 }
13086}
13087
13088void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13089 SimVRegister& zd = ReadVRegister(instr->GetRd());
13090 VectorFormat vform = instr->GetSVEVectorFormat();
13091 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013092 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013093 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013094 break;
13095 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013096 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013097 break;
13098 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013099 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013100 break;
13101 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013102 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13103 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013104 default:
13105 VIXL_UNIMPLEMENTED();
13106 break;
13107 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013108}
13109
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013110void Simulator::VisitSVETableLookup(const Instruction* instr) {
13111 SimVRegister& zd = ReadVRegister(instr->GetRd());
13112 switch (instr->Mask(SVETableLookupMask)) {
13113 case TBL_z_zz_1:
13114 Table(instr->GetSVEVectorFormat(),
13115 zd,
13116 ReadVRegister(instr->GetRn()),
13117 ReadVRegister(instr->GetRm()));
13118 return;
13119 default:
13120 break;
13121 }
13122}
13123
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013124void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013125 VectorFormat vform = instr->GetSVEVectorFormat();
13126 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13127 SimPRegister& pn = ReadPRegister(instr->GetPn());
13128
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013129 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013130 case CNTP_r_p_p: {
13131 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013132 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013133 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013134 default:
13135 VIXL_UNIMPLEMENTED();
13136 break;
13137 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013138}
13139
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013140void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13141 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080013142 SimPRegister& pd = ReadPRegister(instr->GetPd());
13143 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13144 SimPRegister& pn = ReadPRegister(instr->GetPn());
13145 SimPRegister& pm = ReadPRegister(instr->GetPm());
13146 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070013147 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013148 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013149 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013150 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013151 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013152 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013153 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013154 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013155 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013156 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013157 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013158 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013159 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013160 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013161 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070013162 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080013163 result,
13164 pn,
13165 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013166 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080013167 case SEL_p_p_pp:
13168 sel(pd, pg, pn, pm);
13169 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013170 default:
13171 VIXL_UNIMPLEMENTED();
13172 break;
13173 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013174
13175 mov_zeroing(pd, pg, result);
13176 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13177 PredTest(kFormatVnB, pg, pd);
13178 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013179}
13180
Jacob Bramley0ce75842019-07-17 18:12:50 +010013181void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013182 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13183 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13184 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013185 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010013186 pfirst(pdn, pg, pdn);
13187 // TODO: Is this broken when pg == pdn?
13188 PredTest(kFormatVnB, pg, pdn);
13189 break;
13190 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013191 VIXL_UNIMPLEMENTED();
13192 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013193 }
13194}
13195
13196void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013197 // This group only contains PTRUE{S}, and there are no unallocated encodings.
13198 VIXL_STATIC_ASSERT(
13199 SVEPredicateInitializeMask ==
13200 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13201 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13202 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13203
13204 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13205 VectorFormat vform = instr->GetSVEVectorFormat();
13206
13207 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13208 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13209}
13210
13211void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013212 // This group only contains PNEXT, and there are no unallocated encodings.
13213 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13214 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13215
13216 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13217 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13218 VectorFormat vform = instr->GetSVEVectorFormat();
13219
13220 pnext(vform, pdn, pg, pdn);
13221 // TODO: Is this broken when pg == pdn?
13222 PredTest(vform, pg, pdn);
13223}
13224
13225void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13226 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080013227 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13228 LogicPRegister pg(ReadPRegister(instr->GetPn()));
13229 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013230 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13231 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013232 // Do nothing.
13233 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013234 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013235 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013236 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013237 default:
13238 VIXL_UNIMPLEMENTED();
13239 break;
13240 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013241
13242 LogicPRegister ffr(ReadFFR());
13243 mov_zeroing(pd, pg, ffr);
13244
13245 if (flags == SetFlags) {
13246 PredTest(kFormatVnB, pg, pd);
13247 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010013248}
13249
13250void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13251 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013252 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13253 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010013254 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013255 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080013256 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013257 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013258 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013259 VIXL_UNIMPLEMENTED();
13260 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013261 }
13262}
13263
13264void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013265 switch (instr->Mask(SVEPredicateTestMask)) {
13266 case PTEST_p_p:
13267 PredTest(kFormatVnB,
13268 ReadPRegister(instr->ExtractBits(13, 10)),
13269 ReadPRegister(instr->GetPn()));
13270 break;
13271 default:
13272 VIXL_UNIMPLEMENTED();
13273 break;
13274 }
13275}
13276
13277void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013278 switch (instr->Mask(SVEPredicateZeroMask)) {
13279 case PFALSE_p:
13280 pfalse(ReadPRegister(instr->GetPd()));
13281 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013282 default:
13283 VIXL_UNIMPLEMENTED();
13284 break;
13285 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013286}
13287
13288void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080013289 SimPRegister& pd = ReadPRegister(instr->GetPd());
13290 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13291 SimPRegister& pn = ReadPRegister(instr->GetPn());
13292 SimPRegister& pm = ReadPRegister(instr->GetPm());
13293
13294 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013295 switch (instr->Mask(SVEPropagateBreakMask)) {
13296 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013297 set_flags = true;
13298 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013299 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013300 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013301 break;
13302 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013303 set_flags = true;
13304 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013305 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013306 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013307 break;
13308 default:
13309 VIXL_UNIMPLEMENTED();
13310 break;
13311 }
TatWai Chong38303d92019-12-02 15:49:29 -080013312
13313 if (set_flags) {
13314 PredTest(kFormatVnB, pg, pd);
13315 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013316}
13317
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013318void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13319 uint64_t length = 0;
13320 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13321 case ADDPL_r_ri:
13322 length = GetPredicateLengthInBytes();
13323 break;
13324 case ADDVL_r_ri:
13325 length = GetVectorLengthInBytes();
13326 break;
13327 default:
13328 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013329 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013330 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013331 WriteXRegister(instr->GetRd(),
13332 base + (length * instr->GetImmSVEVLScale()),
13333 LogRegWrites,
13334 Reg31IsStackPointer);
13335}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013336
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013337void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13338 int64_t scale = instr->GetImmSVEVLScale();
13339
13340 switch (instr->Mask(SVEStackFrameSizeMask)) {
13341 case RDVL_r_i:
13342 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13343 break;
13344 default:
13345 VIXL_UNIMPLEMENTED();
13346 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013347}
13348
13349void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013350 // The only instruction in this group is `sel`, and there are no unused
13351 // encodings.
13352 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13353
13354 VectorFormat vform = instr->GetSVEVectorFormat();
13355 SimVRegister& zd = ReadVRegister(instr->GetRd());
13356 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13357 SimVRegister& zn = ReadVRegister(instr->GetRn());
13358 SimVRegister& zm = ReadVRegister(instr->GetRm());
13359
13360 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013361}
13362
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013363void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013364 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013365 case SETFFR_f: {
13366 LogicPRegister ffr(ReadFFR());
13367 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013368 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013369 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013370 default:
13371 VIXL_UNIMPLEMENTED();
13372 break;
13373 }
13374}
13375
13376void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013377 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013378 case WRFFR_f_p: {
13379 SimPRegister pn(ReadPRegister(instr->GetPn()));
13380 bool last_active = true;
13381 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13382 bool active = pn.GetBit(i);
13383 if (active && !last_active) {
13384 // `pn` is non-monotonic. This is UNPREDICTABLE.
13385 VIXL_ABORT();
13386 }
13387 last_active = active;
13388 }
13389 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013390 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013391 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013392 default:
13393 VIXL_UNIMPLEMENTED();
13394 break;
13395 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013396}
Alexandre Ramesd3832962016-07-04 15:03:43 +010013397
TatWai Chong6205eb42019-09-24 10:07:20 +010013398void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013399 bool is_signed;
13400 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13401 case LD1B_z_p_bi_u8:
13402 case LD1B_z_p_bi_u16:
13403 case LD1B_z_p_bi_u32:
13404 case LD1B_z_p_bi_u64:
13405 case LD1H_z_p_bi_u16:
13406 case LD1H_z_p_bi_u32:
13407 case LD1H_z_p_bi_u64:
13408 case LD1W_z_p_bi_u32:
13409 case LD1W_z_p_bi_u64:
13410 case LD1D_z_p_bi_u64:
13411 is_signed = false;
13412 break;
13413 case LD1SB_z_p_bi_s16:
13414 case LD1SB_z_p_bi_s32:
13415 case LD1SB_z_p_bi_s64:
13416 case LD1SH_z_p_bi_s32:
13417 case LD1SH_z_p_bi_s64:
13418 case LD1SW_z_p_bi_s64:
13419 is_signed = true;
13420 break;
13421 default:
13422 // This encoding group is complete, so no other values should be possible.
13423 VIXL_UNREACHABLE();
13424 is_signed = false;
13425 break;
13426 }
13427
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013428 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010013429 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13430 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013431 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13432 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13433 uint64_t offset =
13434 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013435 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013436 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013437 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13438 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013439 ReadPRegister(instr->GetPgLow8()),
13440 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013441 addr,
13442 is_signed);
13443}
13444
13445void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13446 const Instruction* instr) {
13447 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010013448 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13449 case LD1B_z_p_br_u8:
13450 case LD1B_z_p_br_u16:
13451 case LD1B_z_p_br_u32:
13452 case LD1B_z_p_br_u64:
13453 case LD1H_z_p_br_u16:
13454 case LD1H_z_p_br_u32:
13455 case LD1H_z_p_br_u64:
13456 case LD1W_z_p_br_u32:
13457 case LD1W_z_p_br_u64:
13458 case LD1D_z_p_br_u64:
13459 is_signed = false;
13460 break;
13461 case LD1SB_z_p_br_s16:
13462 case LD1SB_z_p_br_s32:
13463 case LD1SB_z_p_br_s64:
13464 case LD1SH_z_p_br_s32:
13465 case LD1SH_z_p_br_s64:
13466 case LD1SW_z_p_br_s64:
13467 is_signed = true;
13468 break;
13469 default:
13470 // This encoding group is complete, so no other values should be possible.
13471 VIXL_UNREACHABLE();
13472 is_signed = false;
13473 break;
13474 }
13475
13476 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13477 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13478 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13479 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13480 uint64_t offset = ReadXRegister(instr->GetRm());
13481 offset <<= msize_in_bytes_log2;
13482 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013483 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13484 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013485 ReadPRegister(instr->GetPgLow8()),
13486 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013487 addr,
13488 is_signed);
13489}
13490
Alexandre Ramesd3832962016-07-04 15:03:43 +010013491void Simulator::DoUnreachable(const Instruction* instr) {
13492 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13493 (instr->GetImmException() == kUnreachableOpcode));
13494
13495 fprintf(stream_,
13496 "Hit UNREACHABLE marker at pc=%p.\n",
13497 reinterpret_cast<const void*>(instr));
13498 abort();
13499}
13500
13501
13502void Simulator::DoTrace(const Instruction* instr) {
13503 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13504 (instr->GetImmException() == kTraceOpcode));
13505
13506 // Read the arguments encoded inline in the instruction stream.
13507 uint32_t parameters;
13508 uint32_t command;
13509
13510 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13511 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13512 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13513
13514 switch (command) {
13515 case TRACE_ENABLE:
13516 SetTraceParameters(GetTraceParameters() | parameters);
13517 break;
13518 case TRACE_DISABLE:
13519 SetTraceParameters(GetTraceParameters() & ~parameters);
13520 break;
13521 default:
13522 VIXL_UNREACHABLE();
13523 }
13524
13525 WritePc(instr->GetInstructionAtOffset(kTraceLength));
13526}
13527
13528
13529void Simulator::DoLog(const Instruction* instr) {
13530 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13531 (instr->GetImmException() == kLogOpcode));
13532
13533 // Read the arguments encoded inline in the instruction stream.
13534 uint32_t parameters;
13535
13536 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13537 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13538
13539 // We don't support a one-shot LOG_DISASM.
13540 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13541 // Print the requested information.
13542 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13543 if (parameters & LOG_REGS) PrintRegisters();
13544 if (parameters & LOG_VREGS) PrintVRegisters();
13545
13546 WritePc(instr->GetInstructionAtOffset(kLogLength));
13547}
13548
13549
13550void Simulator::DoPrintf(const Instruction* instr) {
13551 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13552 (instr->GetImmException() == kPrintfOpcode));
13553
13554 // Read the arguments encoded inline in the instruction stream.
13555 uint32_t arg_count;
13556 uint32_t arg_pattern_list;
13557 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13558 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13559 memcpy(&arg_pattern_list,
13560 instr + kPrintfArgPatternListOffset,
13561 sizeof(arg_pattern_list));
13562
13563 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13564 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13565
13566 // We need to call the host printf function with a set of arguments defined by
13567 // arg_pattern_list. Because we don't know the types and sizes of the
13568 // arguments, this is very difficult to do in a robust and portable way. To
13569 // work around the problem, we pick apart the format string, and print one
13570 // format placeholder at a time.
13571
13572 // Allocate space for the format string. We take a copy, so we can modify it.
13573 // Leave enough space for one extra character per expected argument (plus the
13574 // '\0' termination).
13575 const char* format_base = ReadRegister<const char*>(0);
13576 VIXL_ASSERT(format_base != NULL);
13577 size_t length = strlen(format_base) + 1;
13578 char* const format = new char[length + arg_count];
13579
13580 // A list of chunks, each with exactly one format placeholder.
13581 const char* chunks[kPrintfMaxArgCount];
13582
13583 // Copy the format string and search for format placeholders.
13584 uint32_t placeholder_count = 0;
13585 char* format_scratch = format;
13586 for (size_t i = 0; i < length; i++) {
13587 if (format_base[i] != '%') {
13588 *format_scratch++ = format_base[i];
13589 } else {
13590 if (format_base[i + 1] == '%') {
13591 // Ignore explicit "%%" sequences.
13592 *format_scratch++ = format_base[i];
13593 i++;
13594 // Chunks after the first are passed as format strings to printf, so we
13595 // need to escape '%' characters in those chunks.
13596 if (placeholder_count > 0) *format_scratch++ = format_base[i];
13597 } else {
13598 VIXL_CHECK(placeholder_count < arg_count);
13599 // Insert '\0' before placeholders, and store their locations.
13600 *format_scratch++ = '\0';
13601 chunks[placeholder_count++] = format_scratch;
13602 *format_scratch++ = format_base[i];
13603 }
13604 }
13605 }
13606 VIXL_CHECK(placeholder_count == arg_count);
13607
13608 // Finally, call printf with each chunk, passing the appropriate register
13609 // argument. Normally, printf returns the number of bytes transmitted, so we
13610 // can emulate a single printf call by adding the result from each chunk. If
13611 // any call returns a negative (error) value, though, just return that value.
13612
13613 printf("%s", clr_printf);
13614
13615 // Because '\0' is inserted before each placeholder, the first string in
13616 // 'format' contains no format placeholders and should be printed literally.
13617 int result = printf("%s", format);
13618 int pcs_r = 1; // Start at x1. x0 holds the format string.
13619 int pcs_f = 0; // Start at d0.
13620 if (result >= 0) {
13621 for (uint32_t i = 0; i < placeholder_count; i++) {
13622 int part_result = -1;
13623
13624 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13625 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13626 switch (arg_pattern) {
13627 case kPrintfArgW:
13628 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13629 break;
13630 case kPrintfArgX:
13631 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13632 break;
13633 case kPrintfArgD:
13634 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13635 break;
13636 default:
13637 VIXL_UNREACHABLE();
13638 }
13639
13640 if (part_result < 0) {
13641 // Handle error values.
13642 result = part_result;
13643 break;
13644 }
13645
13646 result += part_result;
13647 }
13648 }
13649
13650 printf("%s", clr_normal);
13651
13652 // Printf returns its result in x0 (just like the C library's printf).
13653 WriteXRegister(0, result);
13654
13655 // The printf parameters are inlined in the code, so skip them.
13656 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13657
13658 // Set LR as if we'd just called a native printf function.
13659 WriteLr(ReadPc());
13660
13661 delete[] format;
13662}
13663
Alexandre Rames064e02d2016-07-12 11:53:13 +010013664
Alexandre Ramesca73ba02016-07-28 09:16:03 +010013665#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010013666void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013667 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013668 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13669 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013670 uintptr_t call_wrapper_address =
13671 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13672 uintptr_t function_address =
13673 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080013674 RuntimeCallType call_type = static_cast<RuntimeCallType>(
13675 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013676 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010013677 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013678
13679 if (call_type == kCallRuntime) {
13680 WriteRegister(kLinkRegCode,
13681 instr->GetInstructionAtOffset(kRuntimeCallLength));
13682 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013683 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013684 // Read the return address from `lr` and write it into `pc`.
13685 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013686}
13687#else
13688void Simulator::DoRuntimeCall(const Instruction* instr) {
13689 USE(instr);
13690 VIXL_UNREACHABLE();
13691}
13692#endif
13693
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013694
13695void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
13696 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
13697
13698 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013699 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013700 std::numeric_limits<ElementType>::max());
13701
13702 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
13703
13704 size_t element_size = sizeof(ElementType);
13705 size_t offset = kConfigureCPUFeaturesListOffset;
13706
13707 // Read the kNone-terminated list of features.
13708 CPUFeatures parameters;
13709 while (true) {
13710 ElementType feature = Memory::Read<ElementType>(instr + offset);
13711 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013712 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013713 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
13714 }
13715
13716 switch (instr->GetImmException()) {
13717 case kSetCPUFeaturesOpcode:
13718 SetCPUFeatures(parameters);
13719 break;
13720 case kEnableCPUFeaturesOpcode:
13721 GetCPUFeatures()->Combine(parameters);
13722 break;
13723 case kDisableCPUFeaturesOpcode:
13724 GetCPUFeatures()->Remove(parameters);
13725 break;
13726 default:
13727 VIXL_UNREACHABLE();
13728 break;
13729 }
13730
13731 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
13732}
13733
13734
13735void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
13736 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13737 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
13738 USE(instr);
13739
13740 saved_cpu_features_.push_back(*GetCPUFeatures());
13741}
13742
13743
13744void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
13745 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13746 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
13747 USE(instr);
13748
13749 SetCPUFeatures(saved_cpu_features_.back());
13750 saved_cpu_features_.pop_back();
13751}
13752
13753
Alexandre Ramesd3832962016-07-04 15:03:43 +010013754} // namespace aarch64
13755} // namespace vixl
13756
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010013757#endif // VIXL_INCLUDE_SIMULATOR_AARCH64