blob: 0d7dfcbaf2e29f685e35320e5c7e40ea0132af0f [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),
Martyn Capewellc4b56bb2020-10-14 15:45:14 +010072 {"adclb_z_zzz", &Simulator::SimulateSVEAddSubCarry},
73 {"adclt_z_zzz", &Simulator::SimulateSVEAddSubCarry},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +010074 {"addhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
75 {"addhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewellfa1e2112020-09-16 16:53:09 +010076 {"addp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
Martyn Capewellb1b95782020-10-23 15:59:49 +010077 {"bcax_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +010078 {"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},
Martyn Capewellb1b95782020-10-23 15:59:49 +010081 {"bsl1n_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
82 {"bsl2n_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
83 {"bsl_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +010084 {"cadd_z_zz", &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +000085 {"cdot_z_zzz", &Simulator::SimulateSVEComplexDotProduct},
86 {"cdot_z_zzzi_d", &Simulator::SimulateSVEComplexDotProduct},
87 {"cdot_z_zzzi_s", &Simulator::SimulateSVEComplexDotProduct},
Martyn Capewell6bf28752020-08-05 11:57:06 +010088 {"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},
Martyn Capewellb1b95782020-10-23 15:59:49 +010091 {"eor3_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +010092 {"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},
Martyn Capewell8f4e1692020-11-06 14:16:14 +0000130 {"mla_z_zzzi_d", &Simulator::SimulateSVEMlaMlsIndex},
131 {"mla_z_zzzi_h", &Simulator::SimulateSVEMlaMlsIndex},
132 {"mla_z_zzzi_s", &Simulator::SimulateSVEMlaMlsIndex},
133 {"mls_z_zzzi_d", &Simulator::SimulateSVEMlaMlsIndex},
134 {"mls_z_zzzi_h", &Simulator::SimulateSVEMlaMlsIndex},
135 {"mls_z_zzzi_s", &Simulator::SimulateSVEMlaMlsIndex},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100136 {"mul_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
Martyn Capewellf272b9c2020-11-05 18:30:16 +0000137 {"mul_z_zzi_d", &Simulator::SimulateSVEMulIndex},
138 {"mul_z_zzi_h", &Simulator::SimulateSVEMulIndex},
139 {"mul_z_zzi_s", &Simulator::SimulateSVEMulIndex},
Martyn Capewellb1b95782020-10-23 15:59:49 +0100140 {"nbsl_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100141 {"nmatch_p_p_zz", &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
142 {"pmul_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700143 {"pmullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
144 {"pmullt_z_zz", &Simulator::SimulateSVEIntMulLongVec},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +0100145 {"raddhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
146 {"raddhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100147 {"rshrnb_z_zi", &Simulator::SimulateSVENarrow},
148 {"rshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +0100149 {"rsubhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
150 {"rsubhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100151 {"saba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
Martyn Capewell67d2f822020-10-13 16:39:33 +0100152 {"sabalb_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
153 {"sabalt_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100154 {"sabdlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
155 {"sabdlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100156 {"sadalp_z_p_z", &Simulator::Simulate_ZdaT_PgM_ZnTb},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100157 {"saddlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
158 {"saddlbt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
159 {"saddlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100160 {"saddwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
161 {"saddwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100162 {"sbclb_z_zzz", &Simulator::SimulateSVEAddSubCarry},
163 {"sbclt_z_zzz", &Simulator::SimulateSVEAddSubCarry},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100164 {"shadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100165 {"shrnb_z_zi", &Simulator::SimulateSVENarrow},
166 {"shrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100167 {"shsub_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
168 {"shsubr_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100169 {"sli_z_zzi", &Simulator::Simulate_ZdT_ZnT_const},
Martyn Capewellfa1e2112020-09-16 16:53:09 +0100170 {"smaxp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
171 {"sminp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100172 {"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},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700185 {"smullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700186 {"smullb_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100187 {"smullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700188 {"smullt_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700189 {"smullt_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100190 {"smullt_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +0000191 {"splice_z_p_zz_con", &Simulator::VisitSVEVectorSplice},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100192 {"sqabs_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
Martyn Capewell9b532192020-09-15 16:20:11 +0100193 {"sqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100194 {"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},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700213 {"sqdmullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700214 {"sqdmullb_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100215 {"sqdmullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700216 {"sqdmullt_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700217 {"sqdmullt_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100218 {"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},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100235 {"sqrshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
236 {"sqrshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100237 {"sqrshrnb_z_zi", &Simulator::SimulateSVENarrow},
238 {"sqrshrnt_z_zi", &Simulator::SimulateSVENarrow},
239 {"sqrshrunb_z_zi", &Simulator::SimulateSVENarrow},
240 {"sqrshrunt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100241 {"sqshl_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100242 {"sqshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
243 {"sqshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100244 {"sqshlu_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100245 {"sqshrnb_z_zi", &Simulator::SimulateSVENarrow},
246 {"sqshrnt_z_zi", &Simulator::SimulateSVENarrow},
247 {"sqshrunb_z_zi", &Simulator::SimulateSVENarrow},
248 {"sqshrunt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell9b532192020-09-15 16:20:11 +0100249 {"sqsub_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
250 {"sqsubr_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100251 {"sqxtnb_z_zz", &Simulator::SimulateSVENarrow},
252 {"sqxtnt_z_zz", &Simulator::SimulateSVENarrow},
253 {"sqxtunb_z_zz", &Simulator::SimulateSVENarrow},
254 {"sqxtunt_z_zz", &Simulator::SimulateSVENarrow},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100255 {"srhadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100256 {"sri_z_zzi", &Simulator::Simulate_ZdT_ZnT_const},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100257 {"srshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
258 {"srshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100259 {"srshr_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
260 {"srsra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100261 {"sshllb_z_zi", &Simulator::SimulateSVEShiftLeftImm},
262 {"sshllt_z_zi", &Simulator::SimulateSVEShiftLeftImm},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100263 {"ssra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100264 {"ssublb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
265 {"ssublbt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
266 {"ssublt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
267 {"ssubltb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100268 {"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},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +0100277 {"subhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
278 {"subhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewell9b532192020-09-15 16:20:11 +0100279 {"suqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell99c60492020-10-30 08:14:39 +0000280 {"tbl_z_zz_2", &Simulator::VisitSVETableLookup},
281 {"tbx_z_zz", &Simulator::VisitSVETableLookup},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100282 {"uaba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
Martyn Capewell67d2f822020-10-13 16:39:33 +0100283 {"uabalb_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
284 {"uabalt_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100285 {"uabdlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
286 {"uabdlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100287 {"uadalp_z_p_z", &Simulator::Simulate_ZdaT_PgM_ZnTb},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100288 {"uaddlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
289 {"uaddlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100290 {"uaddwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
291 {"uaddwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100292 {"uhadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
293 {"uhsub_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
294 {"uhsubr_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewellfa1e2112020-09-16 16:53:09 +0100295 {"umaxp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
296 {"uminp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100297 {"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},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700310 {"umullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700311 {"umullb_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100312 {"umullb_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700313 {"umullt_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700314 {"umullt_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100315 {"umullt_z_zzi_s", &Simulator::Simulate_ZdS_ZnH_ZmH_imm},
Martyn Capewell9b532192020-09-15 16:20:11 +0100316 {"uqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100317 {"uqrshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
318 {"uqrshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100319 {"uqrshrnb_z_zi", &Simulator::SimulateSVENarrow},
320 {"uqrshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100321 {"uqshl_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100322 {"uqshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
323 {"uqshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100324 {"uqshrnb_z_zi", &Simulator::SimulateSVENarrow},
325 {"uqshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell9b532192020-09-15 16:20:11 +0100326 {"uqsub_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
327 {"uqsubr_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100328 {"uqxtnb_z_zz", &Simulator::SimulateSVENarrow},
329 {"uqxtnt_z_zz", &Simulator::SimulateSVENarrow},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100330 {"urecpe_z_p_z", &Simulator::Simulate_ZdS_PgM_ZnS},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100331 {"urhadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100332 {"urshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
333 {"urshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100334 {"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},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100337 {"ushllb_z_zi", &Simulator::SimulateSVEShiftLeftImm},
338 {"ushllt_z_zi", &Simulator::SimulateSVEShiftLeftImm},
Martyn Capewell9b532192020-09-15 16:20:11 +0100339 {"usqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100340 {"usra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100341 {"usublb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
342 {"usublt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100343 {"usubwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
344 {"usubwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
Martyn Capewellf0844012020-10-23 16:38:26 +0100345 {"whilege_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
346 {"whilegt_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
347 {"whilehi_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
348 {"whilehs_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100349 {"whilerw_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
350 {"whilewr_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
Martyn Capewell97ca8062020-10-23 14:45:14 +0100351 {"xar_z_zzi", &Simulator::SimulateSVEExclusiveOrRotate},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100352};
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) {
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100743 std::pair<uint64_t, uint8_t> result_and_flags =
744 AddWithCarry(reg_size, left, right, carry_in);
745 if (set_flags) {
746 uint8_t flags = result_and_flags.second;
747 ReadNzcv().SetN((flags >> 3) & 1);
748 ReadNzcv().SetZ((flags >> 2) & 1);
749 ReadNzcv().SetC((flags >> 1) & 1);
750 ReadNzcv().SetV((flags >> 0) & 1);
751 LogSystemRegister(NZCV);
752 }
753 return result_and_flags.first;
754}
755
756std::pair<uint64_t, uint8_t> Simulator::AddWithCarry(unsigned reg_size,
757 uint64_t left,
758 uint64_t right,
759 int carry_in) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100760 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
761 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
762
763 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
764 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
765 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
766
767 left &= reg_mask;
768 right &= reg_mask;
769 uint64_t result = (left + right + carry_in) & reg_mask;
770
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100771 // NZCV bits, ordered N in bit 3 to V in bit 0.
772 uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0;
773 nzcv |= CalcZFlag(result) ? 4 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100774
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100775 // Compute the C flag by comparing the result to the max unsigned integer.
776 uint64_t max_uint_2op = max_uint - carry_in;
777 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
778 nzcv |= C ? 2 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100779
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100780 // Overflow iff the sign bit is the same for the two inputs and different
781 // for the result.
782 uint64_t left_sign = left & sign_mask;
783 uint64_t right_sign = right & sign_mask;
784 uint64_t result_sign = result & sign_mask;
785 bool V = (left_sign == right_sign) && (left_sign != result_sign);
786 nzcv |= V ? 1 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100787
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100788 return std::make_pair(result, nzcv);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100789}
790
Alexandre Ramesd3832962016-07-04 15:03:43 +0100791int64_t Simulator::ShiftOperand(unsigned reg_size,
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000792 uint64_t uvalue,
Alexandre Ramesd3832962016-07-04 15:03:43 +0100793 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100794 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800795 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
796 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000797 if (amount > 0) {
798 uint64_t mask = GetUintMask(reg_size);
799 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
800 // The behavior is undefined in c++ if the shift amount greater than or
801 // equal to the register lane size. Work out the shifted result based on
802 // architectural behavior before performing the c++ type shfit operations.
803 switch (shift_type) {
804 case LSL:
805 if (amount >= reg_size) {
806 return UINT64_C(0);
807 }
808 uvalue <<= amount;
809 break;
810 case LSR:
811 if (amount >= reg_size) {
812 return UINT64_C(0);
813 }
814 uvalue >>= amount;
815 break;
816 case ASR:
817 if (amount >= reg_size) {
818 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
819 }
820 uvalue >>= amount;
821 if (is_negative) {
822 // Simulate sign-extension to 64 bits.
823 uvalue |= ~UINT64_C(0) << (reg_size - amount);
824 }
825 break;
826 case ROR: {
827 uvalue = RotateRight(uvalue, amount, reg_size);
828 break;
TatWai Chong29a0c432019-11-06 22:20:44 -0800829 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000830 default:
831 VIXL_UNIMPLEMENTED();
832 return 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100833 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000834 uvalue &= mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100835 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000836
837 int64_t result;
838 memcpy(&result, &uvalue, sizeof(result));
839 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100840}
841
842
843int64_t Simulator::ExtendValue(unsigned reg_size,
844 int64_t value,
845 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100846 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100847 switch (extend_type) {
848 case UXTB:
849 value &= kByteMask;
850 break;
851 case UXTH:
852 value &= kHalfWordMask;
853 break;
854 case UXTW:
855 value &= kWordMask;
856 break;
857 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000858 value &= kByteMask;
859 if ((value & 0x80) != 0) {
860 value |= ~UINT64_C(0) << 8;
861 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100862 break;
863 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000864 value &= kHalfWordMask;
865 if ((value & 0x8000) != 0) {
866 value |= ~UINT64_C(0) << 16;
867 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100868 break;
869 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000870 value &= kWordMask;
871 if ((value & 0x80000000) != 0) {
872 value |= ~UINT64_C(0) << 32;
873 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100874 break;
875 case UXTX:
876 case SXTX:
877 break;
878 default:
879 VIXL_UNREACHABLE();
880 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000881 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100882}
883
884
885void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
886 AssertSupportedFPCR();
887
888 // TODO: This assumes that the C++ implementation handles comparisons in the
889 // way that we expect (as per AssertSupportedFPCR()).
890 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100891 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100892 ReadNzcv().SetRawValue(FPUnorderedFlag);
893 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
894 (trap == EnableTrap)) {
895 process_exception = true;
896 }
897 } else if (val0 < val1) {
898 ReadNzcv().SetRawValue(FPLessThanFlag);
899 } else if (val0 > val1) {
900 ReadNzcv().SetRawValue(FPGreaterThanFlag);
901 } else if (val0 == val1) {
902 ReadNzcv().SetRawValue(FPEqualFlag);
903 } else {
904 VIXL_UNREACHABLE();
905 }
906 LogSystemRegister(NZCV);
907 if (process_exception) FPProcessException();
908}
909
910
Alexandre Rames868bfc42016-07-19 17:10:48 +0100911uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
912 VIXL_ASSERT(mem_op.IsValid());
913 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
914 if (mem_op.IsImmediateOffset()) {
915 return base + mem_op.GetOffset();
916 } else {
917 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
918 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100919 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100920 if (mem_op.GetShift() != NO_SHIFT) {
921 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
922 }
923 if (mem_op.GetExtend() != NO_EXTEND) {
924 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
925 }
926 return static_cast<uint64_t>(base + offset);
927 }
928}
929
930
Alexandre Ramesd3832962016-07-04 15:03:43 +0100931Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
932 unsigned reg_size, unsigned lane_size) {
933 VIXL_ASSERT(reg_size >= lane_size);
934
935 uint32_t format = 0;
936 if (reg_size != lane_size) {
937 switch (reg_size) {
938 default:
939 VIXL_UNREACHABLE();
940 break;
941 case kQRegSizeInBytes:
942 format = kPrintRegAsQVector;
943 break;
944 case kDRegSizeInBytes:
945 format = kPrintRegAsDVector;
946 break;
947 }
948 }
949
950 switch (lane_size) {
951 default:
952 VIXL_UNREACHABLE();
953 break;
954 case kQRegSizeInBytes:
955 format |= kPrintReg1Q;
956 break;
957 case kDRegSizeInBytes:
958 format |= kPrintReg1D;
959 break;
960 case kSRegSizeInBytes:
961 format |= kPrintReg1S;
962 break;
963 case kHRegSizeInBytes:
964 format |= kPrintReg1H;
965 break;
966 case kBRegSizeInBytes:
967 format |= kPrintReg1B;
968 break;
969 }
970 // These sizes would be duplicate case labels.
971 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
972 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
973 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
974 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
975
976 return static_cast<PrintRegisterFormat>(format);
977}
978
979
980Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
981 VectorFormat vform) {
982 switch (vform) {
983 default:
984 VIXL_UNREACHABLE();
985 return kPrintReg16B;
986 case kFormat16B:
987 return kPrintReg16B;
988 case kFormat8B:
989 return kPrintReg8B;
990 case kFormat8H:
991 return kPrintReg8H;
992 case kFormat4H:
993 return kPrintReg4H;
994 case kFormat4S:
995 return kPrintReg4S;
996 case kFormat2S:
997 return kPrintReg2S;
998 case kFormat2D:
999 return kPrintReg2D;
1000 case kFormat1D:
1001 return kPrintReg1D;
1002
1003 case kFormatB:
1004 return kPrintReg1B;
1005 case kFormatH:
1006 return kPrintReg1H;
1007 case kFormatS:
1008 return kPrintReg1S;
1009 case kFormatD:
1010 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +01001011
1012 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001013 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +01001014 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001015 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +01001016 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001017 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +01001018 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001019 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001020 }
1021}
1022
1023
1024Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1025 VectorFormat vform) {
1026 switch (vform) {
1027 default:
1028 VIXL_UNREACHABLE();
1029 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001030 case kFormat8H:
1031 return kPrintReg8HFP;
1032 case kFormat4H:
1033 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001034 case kFormat4S:
1035 return kPrintReg4SFP;
1036 case kFormat2S:
1037 return kPrintReg2SFP;
1038 case kFormat2D:
1039 return kPrintReg2DFP;
1040 case kFormat1D:
1041 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001042 case kFormatH:
1043 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001044 case kFormatS:
1045 return kPrintReg1SFP;
1046 case kFormatD:
1047 return kPrintReg1DFP;
1048 }
1049}
1050
Jacob Bramley423e5422019-11-13 19:15:55 +00001051void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001052 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +00001053 if (i == kSpRegCode) i = kSPRegInternalCode;
1054 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001055 }
1056}
1057
Jacob Bramley423e5422019-11-13 19:15:55 +00001058void Simulator::PrintVRegisters() {
1059 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1060 PrintVRegister(i);
1061 }
1062}
1063
1064void Simulator::PrintZRegisters() {
1065 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
1066 PrintZRegister(i);
1067 }
1068}
1069
1070void Simulator::PrintWrittenRegisters() {
1071 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1072 if (registers_[i].WrittenSinceLastLog()) {
1073 if (i == kSpRegCode) i = kSPRegInternalCode;
1074 PrintRegister(i);
1075 }
1076 }
1077}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001078
1079void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001080 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001081 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001082 if (vregisters_[i].WrittenSinceLastLog()) {
1083 // Z registers are initialised in the constructor before the user can
1084 // configure the CPU features, so we must also check for SVE here.
1085 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
1086 PrintZRegister(i);
1087 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00001088 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001089 }
1090 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001091 }
1092}
1093
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001094void Simulator::PrintWrittenPRegisters() {
1095 // P registers are initialised in the constructor before the user can
1096 // configure the CPU features, so we must check for SVE here.
1097 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
1098 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
1099 if (pregisters_[i].WrittenSinceLastLog()) {
1100 PrintPRegister(i);
1101 }
1102 }
Jacob Bramley0d754e92020-06-18 10:59:09 +01001103 if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001104}
1105
Alexandre Ramesd3832962016-07-04 15:03:43 +01001106void Simulator::PrintSystemRegisters() {
1107 PrintSystemRegister(NZCV);
1108 PrintSystemRegister(FPCR);
1109}
1110
Jacob Bramley423e5422019-11-13 19:15:55 +00001111void Simulator::PrintRegisterValue(const uint8_t* value,
1112 int value_size,
1113 PrintRegisterFormat format) {
1114 int print_width = GetPrintRegSizeInBytes(format);
1115 VIXL_ASSERT(print_width <= value_size);
1116 for (int i = value_size - 1; i >= print_width; i--) {
1117 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +01001118 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +00001119 // If we aren't explicitly printing a partial value, ensure that the
1120 // unprinted bits are zero.
1121 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001122 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001123 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +00001124 for (int i = print_width - 1; i >= 0; i--) {
1125 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001126 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001127}
1128
Jacob Bramley423e5422019-11-13 19:15:55 +00001129void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
1130 uint16_t lane_mask,
1131 PrintRegisterFormat format) {
1132 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
1133 int lane_size = GetPrintRegLaneSizeInBytes(format);
1134 fprintf(stream_, " (");
1135 bool last_inactive = false;
1136 const char* sep = "";
1137 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
1138 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
1139 if (access) {
1140 // Read the lane as a double, so we can format all FP types in the same
1141 // way. We squash NaNs, and a double can exactly represent any other value
1142 // that the smaller types can represent, so this is lossless.
1143 double element;
1144 switch (lane_size) {
1145 case kHRegSizeInBytes: {
1146 Float16 element_fp16;
1147 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
1148 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
1149 element = FPToDouble(element_fp16, kUseDefaultNaN);
1150 break;
1151 }
1152 case kSRegSizeInBytes: {
1153 float element_fp32;
1154 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
1155 element = static_cast<double>(element_fp32);
1156 break;
1157 }
1158 case kDRegSizeInBytes: {
1159 memcpy(&element, &value[i * lane_size], sizeof(element));
1160 break;
1161 }
1162 default:
1163 VIXL_UNREACHABLE();
1164 fprintf(stream_, "{UnknownFPValue}");
1165 continue;
1166 }
1167 if (IsNaN(element)) {
1168 // The fprintf behaviour for NaNs is implementation-defined. Always
1169 // print "nan", so that traces are consistent.
1170 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
1171 } else {
1172 fprintf(stream_,
1173 "%s%s%#.4g%s",
1174 sep,
1175 clr_vreg_value,
1176 element,
1177 clr_normal);
1178 }
1179 last_inactive = false;
1180 } else if (!last_inactive) {
1181 // Replace each contiguous sequence of inactive lanes with "...".
1182 fprintf(stream_, "%s...", sep);
1183 last_inactive = true;
1184 }
1185 }
1186 fprintf(stream_, ")");
1187}
1188
1189void Simulator::PrintRegister(int code,
1190 PrintRegisterFormat format,
1191 const char* suffix) {
1192 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
1193 (static_cast<unsigned>(code) == kSPRegInternalCode));
1194 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
1195 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
1196
1197 SimRegister* reg;
1198 SimRegister zero;
1199 if (code == kZeroRegCode) {
1200 reg = &zero;
1201 } else {
1202 // registers_[31] holds the SP.
1203 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1204 reg = &registers_[code % kNumberOfRegisters];
1205 }
1206
1207 // We trace register writes as whole register values, implying that any
1208 // unprinted bits are all zero:
1209 // "# x{code}: 0x{-----value----}"
1210 // "# w{code}: 0x{-value}"
1211 // Stores trace partial register values, implying nothing about the unprinted
1212 // bits:
1213 // "# x{code}<63:0>: 0x{-----value----}"
1214 // "# x{code}<31:0>: 0x{-value}"
1215 // "# x{code}<15:0>: 0x{--}"
1216 // "# x{code}<7:0>: 0x{}"
1217
1218 bool is_partial = (format & kPrintRegPartial) != 0;
1219 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1220 std::stringstream name;
1221 if (is_partial) {
1222 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
1223 } else {
1224 // Notify the register that it has been logged, but only if we're printing
1225 // all of it.
1226 reg->NotifyRegisterLogged();
1227 switch (print_reg_size) {
1228 case kWRegSize:
1229 name << WRegNameForCode(code);
1230 break;
1231 case kXRegSize:
1232 name << XRegNameForCode(code);
1233 break;
1234 default:
1235 VIXL_UNREACHABLE();
1236 return;
1237 }
1238 }
1239
1240 fprintf(stream_,
1241 "# %s%*s: %s",
1242 clr_reg_name,
1243 kPrintRegisterNameFieldWidth,
1244 name.str().c_str(),
1245 clr_reg_value);
1246 PrintRegisterValue(*reg, format);
1247 fprintf(stream_, "%s%s", clr_normal, suffix);
1248}
1249
1250void Simulator::PrintVRegister(int code,
1251 PrintRegisterFormat format,
1252 const char* suffix) {
1253 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
1254 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
1255 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
1256 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
1257
1258 // We trace register writes as whole register values, implying that any
1259 // unprinted bits are all zero:
1260 // "# v{code}: 0x{-------------value------------}"
1261 // "# d{code}: 0x{-----value----}"
1262 // "# s{code}: 0x{-value}"
1263 // "# h{code}: 0x{--}"
1264 // "# b{code}: 0x{}"
1265 // Stores trace partial register values, implying nothing about the unprinted
1266 // bits:
1267 // "# v{code}<127:0>: 0x{-------------value------------}"
1268 // "# v{code}<63:0>: 0x{-----value----}"
1269 // "# v{code}<31:0>: 0x{-value}"
1270 // "# v{code}<15:0>: 0x{--}"
1271 // "# v{code}<7:0>: 0x{}"
1272
1273 bool is_partial = ((format & kPrintRegPartial) != 0);
1274 std::stringstream name;
1275 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1276 if (is_partial) {
1277 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1278 } else {
1279 // Notify the register that it has been logged, but only if we're printing
1280 // all of it.
1281 vregisters_[code].NotifyRegisterLogged();
1282 switch (print_reg_size) {
1283 case kBRegSize:
1284 name << BRegNameForCode(code);
1285 break;
1286 case kHRegSize:
1287 name << HRegNameForCode(code);
1288 break;
1289 case kSRegSize:
1290 name << SRegNameForCode(code);
1291 break;
1292 case kDRegSize:
1293 name << DRegNameForCode(code);
1294 break;
1295 case kQRegSize:
1296 name << VRegNameForCode(code);
1297 break;
1298 default:
1299 VIXL_UNREACHABLE();
1300 return;
1301 }
1302 }
1303
1304 fprintf(stream_,
1305 "# %s%*s: %s",
1306 clr_vreg_name,
1307 kPrintRegisterNameFieldWidth,
1308 name.str().c_str(),
1309 clr_vreg_value);
1310 PrintRegisterValue(vregisters_[code], format);
1311 fprintf(stream_, "%s", clr_normal);
1312 if ((format & kPrintRegAsFP) != 0) {
1313 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1314 }
1315 fprintf(stream_, "%s", suffix);
1316}
1317
1318void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1319 int reg_count,
1320 uint16_t focus_mask,
1321 PrintRegisterFormat format) {
1322 bool print_fp = (format & kPrintRegAsFP) != 0;
1323 // Suppress FP formatting, so we can specify the lanes we're interested in.
1324 PrintRegisterFormat format_no_fp =
1325 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1326
1327 for (int r = 0; r < reg_count; r++) {
1328 int code = (rt_code + r) % kNumberOfVRegisters;
1329 PrintVRegister(code, format_no_fp, "");
1330 if (print_fp) {
1331 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1332 }
1333 fprintf(stream_, "\n");
1334 }
1335}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001336
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001337void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1338 int q_index,
1339 int reg_count,
1340 uint16_t focus_mask,
1341 PrintRegisterFormat format) {
1342 bool print_fp = (format & kPrintRegAsFP) != 0;
1343 // Suppress FP formatting, so we can specify the lanes we're interested in.
1344 PrintRegisterFormat format_no_fp =
1345 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001346
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001347 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001348
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001349 const unsigned size = kQRegSizeInBytes;
1350 unsigned byte_index = q_index * size;
1351 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1352 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001353
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001354 for (int r = 0; r < reg_count; r++) {
1355 int code = (rt_code + r) % kNumberOfZRegisters;
1356 PrintPartialZRegister(code, q_index, format_no_fp, "");
1357 if (print_fp) {
1358 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001359 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001360 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001361 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001362}
1363
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001364void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1365 // We're going to print the register in parts, so force a partial format.
1366 format = GetPrintRegPartial(format);
1367 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1368 int vl = GetVectorLengthInBits();
1369 VIXL_ASSERT((vl % kQRegSize) == 0);
1370 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1371 PrintPartialZRegister(code, i, format);
1372 }
1373 vregisters_[code].NotifyRegisterLogged();
1374}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001375
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001376void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1377 // We're going to print the register in parts, so force a partial format.
1378 format = GetPrintRegPartial(format);
1379 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1380 int vl = GetVectorLengthInBits();
1381 VIXL_ASSERT((vl % kQRegSize) == 0);
1382 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1383 PrintPartialPRegister(code, i, format);
1384 }
1385 pregisters_[code].NotifyRegisterLogged();
1386}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001387
Jacob Bramley0d754e92020-06-18 10:59:09 +01001388void Simulator::PrintFFR(PrintRegisterFormat format) {
1389 // We're going to print the register in parts, so force a partial format.
1390 format = GetPrintRegPartial(format);
1391 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1392 int vl = GetVectorLengthInBits();
1393 VIXL_ASSERT((vl % kQRegSize) == 0);
1394 SimPRegister& ffr = ReadFFR();
1395 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1396 PrintPartialPRegister("FFR", ffr, i, format);
1397 }
1398 ffr.NotifyRegisterLogged();
1399}
1400
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001401void Simulator::PrintPartialZRegister(int code,
1402 int q_index,
1403 PrintRegisterFormat format,
1404 const char* suffix) {
1405 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1406 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1407 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1408 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001409
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001410 // We _only_ trace partial Z register values in Q-sized chunks, because
1411 // they're often too large to reasonably fit on a single line. Each line
1412 // implies nothing about the unprinted bits.
1413 // "# z{code}<127:0>: 0x{-------------value------------}"
1414
1415 format = GetPrintRegAsQChunkOfSVE(format);
1416
1417 const unsigned size = kQRegSizeInBytes;
1418 unsigned byte_index = q_index * size;
1419 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1420 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1421
1422 int lsb = q_index * kQRegSize;
1423 int msb = lsb + kQRegSize - 1;
1424 std::stringstream name;
1425 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001426
1427 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001428 "# %s%*s: %s",
1429 clr_vreg_name,
1430 kPrintRegisterNameFieldWidth,
1431 name.str().c_str(),
1432 clr_vreg_value);
1433 PrintRegisterValue(value, size, format);
1434 fprintf(stream_, "%s", clr_normal);
1435 if ((format & kPrintRegAsFP) != 0) {
1436 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1437 }
1438 fprintf(stream_, "%s", suffix);
1439}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001440
Jacob Bramley0d754e92020-06-18 10:59:09 +01001441void Simulator::PrintPartialPRegister(const char* name,
1442 const SimPRegister& reg,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001443 int q_index,
1444 PrintRegisterFormat format,
1445 const char* suffix) {
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001446 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1447 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1448 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1449
1450 // We don't currently use the format for anything here.
1451 USE(format);
1452
1453 // We _only_ trace partial P register values, because they're often too large
1454 // to reasonably fit on a single line. Each line implies nothing about the
1455 // unprinted bits.
1456 //
1457 // We print values in binary, with spaces between each bit, in order for the
1458 // bits to align with the Z register bytes that they predicate.
Jacob Bramley0d754e92020-06-18 10:59:09 +01001459 // "# {name}<15:0>: 0b{-------------value------------}"
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001460
1461 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1462 int lsb = q_index * print_size_in_bits;
1463 int msb = lsb + print_size_in_bits - 1;
Jacob Bramley0d754e92020-06-18 10:59:09 +01001464 std::stringstream prefix;
1465 prefix << name << '<' << msb << ':' << lsb << '>';
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001466
1467 fprintf(stream_,
1468 "# %s%*s: %s0b",
1469 clr_preg_name,
1470 kPrintRegisterNameFieldWidth,
Jacob Bramley0d754e92020-06-18 10:59:09 +01001471 prefix.str().c_str(),
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001472 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001473 for (int i = msb; i >= lsb; i--) {
Jacob Bramley0d754e92020-06-18 10:59:09 +01001474 fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001475 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001476 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001477}
1478
Jacob Bramley0d754e92020-06-18 10:59:09 +01001479void Simulator::PrintPartialPRegister(int code,
1480 int q_index,
1481 PrintRegisterFormat format,
1482 const char* suffix) {
1483 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1484 PrintPartialPRegister(PRegNameForCode(code),
1485 pregisters_[code],
1486 q_index,
1487 format,
1488 suffix);
1489}
1490
Alexandre Ramesd3832962016-07-04 15:03:43 +01001491void Simulator::PrintSystemRegister(SystemRegister id) {
1492 switch (id) {
1493 case NZCV:
1494 fprintf(stream_,
1495 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1496 clr_flag_name,
1497 clr_flag_value,
1498 ReadNzcv().GetN(),
1499 ReadNzcv().GetZ(),
1500 ReadNzcv().GetC(),
1501 ReadNzcv().GetV(),
1502 clr_normal);
1503 break;
1504 case FPCR: {
1505 static const char* rmode[] = {"0b00 (Round to Nearest)",
1506 "0b01 (Round towards Plus Infinity)",
1507 "0b10 (Round towards Minus Infinity)",
1508 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001509 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001510 fprintf(stream_,
1511 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1512 clr_flag_name,
1513 clr_flag_value,
1514 ReadFpcr().GetAHP(),
1515 ReadFpcr().GetDN(),
1516 ReadFpcr().GetFZ(),
1517 rmode[ReadFpcr().GetRMode()],
1518 clr_normal);
1519 break;
1520 }
1521 default:
1522 VIXL_UNREACHABLE();
1523 }
1524}
1525
Jacob Bramley423e5422019-11-13 19:15:55 +00001526uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1527 uint16_t future_access_mask,
1528 int struct_element_count,
1529 int lane_size_in_bytes,
1530 const char* op,
1531 uintptr_t address,
1532 int reg_size_in_bytes) {
1533 // We want to assume that we'll access at least one lane.
1534 VIXL_ASSERT(access_mask != 0);
1535 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1536 (reg_size_in_bytes == kQRegSizeInBytes));
1537 bool started_annotation = false;
1538 // Indent to match the register field, the fixed formatting, and the value
1539 // prefix ("0x"): "# {name}: 0x"
1540 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1541 // First, annotate the lanes (byte by byte).
1542 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1543 bool access = (access_mask & (1 << lane)) != 0;
1544 bool future = (future_access_mask & (1 << lane)) != 0;
1545 if (started_annotation) {
1546 // If we've started an annotation, draw a horizontal line in addition to
1547 // any other symbols.
1548 if (access) {
1549 fprintf(stream_, "─╨");
1550 } else if (future) {
1551 fprintf(stream_, "─║");
1552 } else {
1553 fprintf(stream_, "──");
1554 }
1555 } else {
1556 if (access) {
1557 started_annotation = true;
1558 fprintf(stream_, " â•™");
1559 } else if (future) {
1560 fprintf(stream_, " â•‘");
1561 } else {
1562 fprintf(stream_, " ");
1563 }
1564 }
1565 }
1566 VIXL_ASSERT(started_annotation);
1567 fprintf(stream_, "─ 0x");
1568 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1569 // Print the most-significant struct element first.
1570 const char* sep = "";
1571 for (int i = struct_element_count - 1; i >= 0; i--) {
1572 int offset = lane_size_in_bytes * i;
1573 uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset);
1574 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1575 sep = "'";
1576 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001577 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001578 " %s %s0x%016" PRIxPTR "%s\n",
1579 op,
1580 clr_memory_address,
1581 address,
1582 clr_normal);
1583 return future_access_mask & ~access_mask;
1584}
1585
1586void Simulator::PrintAccess(int code,
1587 PrintRegisterFormat format,
1588 const char* op,
1589 uintptr_t address) {
1590 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1591 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1592 if ((format & kPrintRegPartial) == 0) {
1593 registers_[code].NotifyRegisterLogged();
1594 }
1595 // Scalar-format accesses use a simple format:
1596 // "# {reg}: 0x{value} -> {address}"
1597
1598 // Suppress the newline, so the access annotation goes on the same line.
1599 PrintRegister(code, format, "");
1600 fprintf(stream_,
1601 " %s %s0x%016" PRIxPTR "%s\n",
1602 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001603 clr_memory_address,
1604 address,
1605 clr_normal);
1606}
1607
Jacob Bramley423e5422019-11-13 19:15:55 +00001608void Simulator::PrintVAccess(int code,
1609 PrintRegisterFormat format,
1610 const char* op,
1611 uintptr_t address) {
1612 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001613
Jacob Bramley423e5422019-11-13 19:15:55 +00001614 // Scalar-format accesses use a simple format:
1615 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001616
Jacob Bramley423e5422019-11-13 19:15:55 +00001617 // Suppress the newline, so the access annotation goes on the same line.
1618 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001619 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001620 " %s %s0x%016" PRIxPTR "%s\n",
1621 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001622 clr_memory_address,
1623 address,
1624 clr_normal);
1625}
1626
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001627void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001628 int reg_count,
1629 PrintRegisterFormat format,
1630 const char* op,
1631 uintptr_t address) {
1632 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1633
1634 // For example:
1635 // "# v{code}: 0x{value}"
1636 // "# ...: 0x{value}"
1637 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1638 // "# ╙───── {struct_value} -> {highest_address}"
1639
1640 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001641 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001642
1643 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1644 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1645 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1646 uint16_t access_mask = 1 << i;
1647 VIXL_ASSERT((lane_mask & access_mask) != 0);
1648 lane_mask = PrintPartialAccess(access_mask,
1649 lane_mask,
1650 reg_count,
1651 lane_size_in_bytes,
1652 op,
1653 address + (i * reg_count));
1654 }
1655}
1656
1657void Simulator::PrintVSingleStructAccess(int rt_code,
1658 int reg_count,
1659 int lane,
1660 PrintRegisterFormat format,
1661 const char* op,
1662 uintptr_t address) {
1663 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1664
1665 // For example:
1666 // "# v{code}: 0x{value}"
1667 // "# ...: 0x{value}"
1668 // "# ╙───── {struct_value} -> {address}"
1669
1670 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1671 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1672 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1673 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1674}
1675
1676void Simulator::PrintVReplicatingStructAccess(int rt_code,
1677 int reg_count,
1678 PrintRegisterFormat format,
1679 const char* op,
1680 uintptr_t address) {
1681 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1682
1683 // For example:
1684 // "# v{code}: 0x{value}"
1685 // "# ...: 0x{value}"
1686 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1687
1688 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1689 uint16_t lane_mask = GetPrintRegLaneMask(format);
1690 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1691 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1692}
1693
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001694void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1695 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1696
1697 // Scalar-format accesses are split into separate chunks, each of which uses a
1698 // simple format:
1699 // "# z{code}<127:0>: 0x{value} -> {address}"
1700 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1701 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1702 // etc
1703
1704 int vl = GetVectorLengthInBits();
1705 VIXL_ASSERT((vl % kQRegSize) == 0);
1706 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1707 // Suppress the newline, so the access annotation goes on the same line.
1708 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1709 fprintf(stream_,
1710 " %s %s0x%016" PRIxPTR "%s\n",
1711 op,
1712 clr_memory_address,
1713 address,
1714 clr_normal);
1715 address += kQRegSizeInBytes;
1716 }
1717}
1718
1719void Simulator::PrintZStructAccess(int rt_code,
1720 int reg_count,
1721 const LogicPRegister& pg,
1722 PrintRegisterFormat format,
1723 int msize_in_bytes,
1724 const char* op,
1725 const LogicSVEAddressVector& addr) {
1726 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1727
1728 // For example:
1729 // "# z{code}<255:128>: 0x{value}"
1730 // "# ...<255:128>: 0x{value}"
1731 // "# ║ ╙─ {struct_value} -> {first_address}"
1732 // "# ╙───── {struct_value} -> {last_address}"
1733
1734 // We're going to print the register in parts, so force a partial format.
1735 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1736 format = GetPrintRegPartial(format);
1737
1738 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1739 int vl = GetVectorLengthInBits();
1740 VIXL_ASSERT((vl % kQRegSize) == 0);
1741 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1742 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1743 uint16_t pred =
1744 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1745 if ((pred == 0) && skip_inactive_chunks) continue;
1746
1747 PrintZRegistersForStructuredAccess(rt_code,
1748 q_index,
1749 reg_count,
1750 pred,
1751 format);
1752 if (pred == 0) {
1753 // This register chunk has no active lanes. The loop below would print
1754 // nothing, so leave a blank line to keep structures grouped together.
1755 fprintf(stream_, "#\n");
1756 continue;
1757 }
1758 for (int i = 0; i < lanes_per_q; i++) {
1759 uint16_t access = 1 << (i * esize_in_bytes);
1760 int lane = (q_index * lanes_per_q) + i;
1761 // Skip inactive lanes.
1762 if ((pred & access) == 0) continue;
1763 pred = PrintPartialAccess(access,
1764 pred,
1765 reg_count,
1766 msize_in_bytes,
1767 op,
1768 addr.GetStructAddress(lane));
1769 }
1770 }
1771
1772 // We print the whole register, even for stores.
1773 for (int i = 0; i < reg_count; i++) {
1774 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1775 }
1776}
1777
1778void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1779 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1780
1781 // Scalar-format accesses are split into separate chunks, each of which uses a
1782 // simple format:
1783 // "# p{code}<15:0>: 0b{value} -> {address}"
1784 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1785 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1786 // etc
1787
1788 int vl = GetVectorLengthInBits();
1789 VIXL_ASSERT((vl % kQRegSize) == 0);
1790 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1791 // Suppress the newline, so the access annotation goes on the same line.
1792 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1793 fprintf(stream_,
1794 " %s %s0x%016" PRIxPTR "%s\n",
1795 op,
1796 clr_memory_address,
1797 address,
1798 clr_normal);
1799 address += kQRegSizeInBytes;
1800 }
1801}
1802
Jacob Bramley423e5422019-11-13 19:15:55 +00001803void Simulator::PrintRead(int rt_code,
1804 PrintRegisterFormat format,
1805 uintptr_t address) {
1806 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1807 registers_[rt_code].NotifyRegisterLogged();
1808 PrintAccess(rt_code, format, "<-", address);
1809}
1810
1811void Simulator::PrintExtendingRead(int rt_code,
1812 PrintRegisterFormat format,
1813 int access_size_in_bytes,
1814 uintptr_t address) {
1815 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1816 if (access_size_in_bytes == reg_size_in_bytes) {
1817 // There is no extension here, so print a simple load.
1818 PrintRead(rt_code, format, address);
1819 return;
1820 }
1821 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1822
1823 // For sign- and zero-extension, make it clear that the resulting register
1824 // value is different from what is loaded from memory.
1825 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1826 registers_[rt_code].NotifyRegisterLogged();
1827 PrintRegister(rt_code, format);
1828 PrintPartialAccess(1,
1829 0,
1830 1,
1831 access_size_in_bytes,
1832 "<-",
1833 address,
1834 kXRegSizeInBytes);
1835}
1836
1837void Simulator::PrintVRead(int rt_code,
1838 PrintRegisterFormat format,
1839 uintptr_t address) {
1840 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1841 vregisters_[rt_code].NotifyRegisterLogged();
1842 PrintVAccess(rt_code, format, "<-", address);
1843}
1844
Jacob Bramley423e5422019-11-13 19:15:55 +00001845void Simulator::PrintWrite(int rt_code,
1846 PrintRegisterFormat format,
1847 uintptr_t address) {
1848 // Because this trace doesn't represent a change to the source register's
1849 // value, only print the relevant part of the value.
1850 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001851 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001852 registers_[rt_code].NotifyRegisterLogged();
1853 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001854}
1855
Jacob Bramley423e5422019-11-13 19:15:55 +00001856void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001857 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001858 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001859 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001860 // value, only print the relevant part of the value.
1861 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001862 // It only makes sense to write scalar values here. Vectors are handled by
1863 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001864 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001865 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001866}
1867
Jacob Bramleye79723a2016-06-07 17:50:47 +01001868void Simulator::PrintTakenBranch(const Instruction* target) {
1869 fprintf(stream_,
1870 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1871 clr_branch_marker,
1872 clr_normal,
1873 reinterpret_cast<uint64_t>(target));
1874}
1875
Alexandre Ramesd3832962016-07-04 15:03:43 +01001876// Visitors---------------------------------------------------------------------
1877
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001878
Martyn Capewell8c691852020-07-15 18:33:15 +01001879void Simulator::Visit(Metadata* metadata, const Instruction* instr) {
1880 VIXL_ASSERT(metadata->count("form") > 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001881 std::string form = (*metadata)["form"];
Martyn Capewell8c691852020-07-15 18:33:15 +01001882 if ((form_to_visitor_.count(form) > 0) && form_to_visitor_[form]) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01001883 form_hash_ = Hash(form.c_str());
Martyn Capewell8c691852020-07-15 18:33:15 +01001884 form_to_visitor_[form](this, instr);
1885 } else {
1886 VisitUnimplemented(instr);
1887 }
1888}
1889
Martyn Capewell6bf28752020-08-05 11:57:06 +01001890void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell51643312020-08-24 15:58:57 +01001891 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01001892 SimPRegister& pd = ReadPRegister(instr->GetPd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001893 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001894 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001895 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001896
1897 switch (form_hash_) {
1898 case Hash("match_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001899 match(vform, pd, zn, zm, /* negate_match = */ false);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001900 break;
1901 case Hash("nmatch_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001902 match(vform, pd, zn, zm, /* negate_match = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001903 break;
1904 default:
1905 VIXL_UNIMPLEMENTED();
1906 }
Martyn Capewell51643312020-08-24 15:58:57 +01001907 mov_zeroing(pd, pg, pd);
1908 PredTest(vform, pg, pd);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001909}
1910
Martyn Capewell6bf28752020-08-05 11:57:06 +01001911void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {
Martyn Capewell35636df2020-10-15 15:14:12 +01001912 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01001913 SimPRegister& pd = ReadPRegister(instr->GetPd());
Martyn Capewell35636df2020-10-15 15:14:12 +01001914 uint64_t src1 = ReadXRegister(instr->GetRn());
1915 uint64_t src2 = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001916
Martyn Capewell35636df2020-10-15 15:14:12 +01001917 uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1);
1918 absdiff >>= LaneSizeInBytesLog2FromFormat(vform);
1919
1920 bool no_conflict = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01001921 switch (form_hash_) {
1922 case Hash("whilerw_p_rr"):
Martyn Capewell35636df2020-10-15 15:14:12 +01001923 no_conflict = (absdiff == 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001924 break;
1925 case Hash("whilewr_p_rr"):
Martyn Capewell35636df2020-10-15 15:14:12 +01001926 no_conflict = (absdiff == 0) || (src2 <= src1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001927 break;
1928 default:
1929 VIXL_UNIMPLEMENTED();
1930 }
Martyn Capewell35636df2020-10-15 15:14:12 +01001931
1932 LogicPRegister dst(pd);
1933 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1934 dst.SetActive(vform,
1935 i,
1936 no_conflict || (static_cast<uint64_t>(i) < absdiff));
1937 }
1938
1939 PredTest(vform, GetPTrue(), pd);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001940}
1941
1942void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
1943 SimVRegister& zd = ReadVRegister(instr->GetRd());
1944 USE(zd);
1945 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
1946 USE(zn1);
1947
1948 switch (form_hash_) {
1949 case Hash("ext_z_zi_con"):
1950 VIXL_UNIMPLEMENTED();
1951 break;
1952 default:
1953 VIXL_UNIMPLEMENTED();
1954 }
1955}
1956
1957void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
1958 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001959 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001960 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001961
1962 switch (form_hash_) {
1963 case Hash("histseg_z_zz"):
Martyn Capewell710ec6f2020-10-22 16:56:17 +01001964 if (instr->GetSVEVectorFormat() == kFormatVnB) {
1965 histogram(kFormatVnB,
1966 zd,
1967 GetPTrue(),
1968 zn,
1969 zm,
1970 /* do_segmented = */ true);
1971 } else {
1972 VIXL_UNIMPLEMENTED();
1973 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01001974 break;
1975 case Hash("pmul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07001976 pmul(kFormatVnB, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001977 break;
1978 default:
1979 VIXL_UNIMPLEMENTED();
1980 }
1981}
1982
1983void Simulator::Simulate_ZdD_PgM_ZnS(const Instruction* instr) {
1984 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
1985 USE(pg);
1986 SimVRegister& zd = ReadVRegister(instr->GetRd());
1987 USE(zd);
1988 SimVRegister& zn = ReadVRegister(instr->GetRn());
1989 USE(zn);
1990
1991 switch (form_hash_) {
1992 case Hash("fcvtlt_z_p_z_s2d"):
1993 VIXL_UNIMPLEMENTED();
1994 break;
1995 default:
1996 VIXL_UNIMPLEMENTED();
1997 }
1998}
1999
Martyn Capewellf272b9c2020-11-05 18:30:16 +00002000void Simulator::SimulateSVEMulIndex(const Instruction* instr) {
2001 VectorFormat vform = instr->GetSVEVectorFormat();
2002 SimVRegister& zd = ReadVRegister(instr->GetRd());
2003 SimVRegister& zn = ReadVRegister(instr->GetRn());
2004
2005 // The encoding for B and H-sized lanes are redefined to encode the most
2006 // significant bit of index for H-sized lanes. B-sized lanes are not
2007 // supported.
2008 if (vform == kFormatVnB) vform = kFormatVnH;
2009
2010 VIXL_ASSERT((form_hash_ == Hash("mul_z_zzi_d")) ||
2011 (form_hash_ == Hash("mul_z_zzi_h")) ||
2012 (form_hash_ == Hash("mul_z_zzi_s")));
2013
2014 SimVRegister temp;
2015 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2016 mul(vform, zd, zn, temp);
2017}
2018
Martyn Capewell8f4e1692020-11-06 14:16:14 +00002019void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) {
2020 VectorFormat vform = instr->GetSVEVectorFormat();
2021 SimVRegister& zda = ReadVRegister(instr->GetRd());
2022 SimVRegister& zn = ReadVRegister(instr->GetRn());
2023
2024 // The encoding for B and H-sized lanes are redefined to encode the most
2025 // significant bit of index for H-sized lanes. B-sized lanes are not
2026 // supported.
2027 if (vform == kFormatVnB) vform = kFormatVnH;
2028
2029 VIXL_ASSERT((form_hash_ == Hash("mla_z_zzzi_d")) ||
2030 (form_hash_ == Hash("mla_z_zzzi_h")) ||
2031 (form_hash_ == Hash("mla_z_zzzi_s")) ||
2032 (form_hash_ == Hash("mls_z_zzzi_d")) ||
2033 (form_hash_ == Hash("mls_z_zzzi_h")) ||
2034 (form_hash_ == Hash("mls_z_zzzi_s")));
2035
2036 SimVRegister temp;
2037 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2038 if (instr->ExtractBit(10) == 0) {
2039 mla(vform, zda, zda, zn, temp);
2040 } else {
2041 mls(vform, zda, zda, zn, temp);
2042 }
2043}
2044
Martyn Capewell6bf28752020-08-05 11:57:06 +01002045void Simulator::Simulate_ZdD_ZnD_ZmD_imm(const Instruction* instr) {
2046 SimVRegister& zd = ReadVRegister(instr->GetRd());
2047 USE(zd);
2048 SimVRegister& zn = ReadVRegister(instr->GetRn());
2049 USE(zn);
2050
2051 switch (form_hash_) {
2052 case Hash("mul_z_zzi_d"):
2053 VIXL_UNIMPLEMENTED();
2054 break;
2055 case Hash("sqdmulh_z_zzi_d"):
2056 VIXL_UNIMPLEMENTED();
2057 break;
2058 case Hash("sqrdmulh_z_zzi_d"):
2059 VIXL_UNIMPLEMENTED();
2060 break;
2061 default:
2062 VIXL_UNIMPLEMENTED();
2063 }
2064}
2065
TatWai Chong1719b712020-09-25 18:16:40 -07002066void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002067 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong1719b712020-09-25 18:16:40 -07002068 SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
Martyn Capewell6bf28752020-08-05 11:57:06 +01002069 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong1719b712020-09-25 18:16:40 -07002070
2071 SimVRegister temp, zm_idx, zn_b, zn_t;
2072 // Instead of calling the indexed form of the instruction logic, we call the
2073 // vector form, which can reuse existing function logics without modification.
Martyn Capewell97ca8062020-10-23 14:45:14 +01002074 // Select the specified elements based on the index input and than pack them
2075 // to the corresponding position.
TatWai Chong1719b712020-09-25 18:16:40 -07002076 Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
2077 dup_elements_to_segments(kFormatVnS, temp, zm, index);
2078 pack_even_elements(kFormatVnS, zm_idx, temp);
2079
2080 pack_even_elements(kFormatVnS, zn_b, zn);
2081 pack_odd_elements(kFormatVnS, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002082
2083 switch (form_hash_) {
2084 case Hash("smullb_z_zzi_d"):
2085 VIXL_UNIMPLEMENTED();
2086 break;
2087 case Hash("smullt_z_zzi_d"):
2088 VIXL_UNIMPLEMENTED();
2089 break;
2090 case Hash("sqdmullb_z_zzi_d"):
TatWai Chong1719b712020-09-25 18:16:40 -07002091 sqdmull(kFormatVnD, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002092 break;
2093 case Hash("sqdmullt_z_zzi_d"):
TatWai Chong1719b712020-09-25 18:16:40 -07002094 sqdmull(kFormatVnD, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002095 break;
2096 case Hash("umullb_z_zzi_d"):
2097 VIXL_UNIMPLEMENTED();
2098 break;
2099 case Hash("umullt_z_zzi_d"):
2100 VIXL_UNIMPLEMENTED();
2101 break;
2102 default:
2103 VIXL_UNIMPLEMENTED();
2104 }
2105}
2106
2107void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2108 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2109 USE(pg);
2110 SimVRegister& zd = ReadVRegister(instr->GetRd());
2111 USE(zd);
2112 SimVRegister& zn = ReadVRegister(instr->GetRn());
2113 USE(zn);
2114
2115 switch (form_hash_) {
2116 case Hash("fcvtnt_z_p_z_s2h"):
2117 VIXL_UNIMPLEMENTED();
2118 break;
2119 default:
2120 VIXL_UNIMPLEMENTED();
2121 }
2122}
2123
2124void Simulator::Simulate_ZdH_ZnH_ZmH_imm(const Instruction* instr) {
2125 SimVRegister& zd = ReadVRegister(instr->GetRd());
2126 USE(zd);
2127 SimVRegister& zn = ReadVRegister(instr->GetRn());
2128 USE(zn);
2129
2130 switch (form_hash_) {
2131 case Hash("mul_z_zzi_h"):
2132 VIXL_UNIMPLEMENTED();
2133 break;
2134 case Hash("sqdmulh_z_zzi_h"):
2135 VIXL_UNIMPLEMENTED();
2136 break;
2137 case Hash("sqrdmulh_z_zzi_h"):
2138 VIXL_UNIMPLEMENTED();
2139 break;
2140 default:
2141 VIXL_UNIMPLEMENTED();
2142 }
2143}
2144
2145void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2146 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2147 USE(pg);
2148 SimVRegister& zd = ReadVRegister(instr->GetRd());
2149 USE(zd);
2150 SimVRegister& zn = ReadVRegister(instr->GetRn());
2151 USE(zn);
2152
2153 switch (form_hash_) {
2154 case Hash("fcvtnt_z_p_z_d2s"):
2155 VIXL_UNIMPLEMENTED();
2156 break;
2157 case Hash("fcvtx_z_p_z_d2s"):
2158 VIXL_UNIMPLEMENTED();
2159 break;
2160 case Hash("fcvtxnt_z_p_z_d2s"):
2161 VIXL_UNIMPLEMENTED();
2162 break;
2163 default:
2164 VIXL_UNIMPLEMENTED();
2165 }
2166}
2167
2168void Simulator::Simulate_ZdS_PgM_ZnH(const Instruction* instr) {
2169 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2170 USE(pg);
2171 SimVRegister& zd = ReadVRegister(instr->GetRd());
2172 USE(zd);
2173 SimVRegister& zn = ReadVRegister(instr->GetRn());
2174 USE(zn);
2175
2176 switch (form_hash_) {
2177 case Hash("fcvtlt_z_p_z_h2s"):
2178 VIXL_UNIMPLEMENTED();
2179 break;
2180 default:
2181 VIXL_UNIMPLEMENTED();
2182 }
2183}
2184
2185void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002186 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002187 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002188 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002189 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002190 SimVRegister result;
2191
2192 if (vform != kFormatVnS) {
2193 VIXL_UNIMPLEMENTED();
2194 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002195
2196 switch (form_hash_) {
2197 case Hash("urecpe_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002198 urecpe(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002199 break;
2200 case Hash("ursqrte_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002201 ursqrte(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002202 break;
2203 default:
2204 VIXL_UNIMPLEMENTED();
2205 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002206 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002207}
2208
2209void Simulator::Simulate_ZdS_ZnH_ZmH_imm(const Instruction* instr) {
2210 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong1719b712020-09-25 18:16:40 -07002211 SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
Martyn Capewell6bf28752020-08-05 11:57:06 +01002212 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong1719b712020-09-25 18:16:40 -07002213
2214 SimVRegister temp, zm_idx, zn_b, zn_t;
2215 // Instead of calling the indexed form of the instruction logic, we call the
2216 // vector form, which can reuse existing function logics without modification.
Martyn Capewell97ca8062020-10-23 14:45:14 +01002217 // Select the specified elements based on the index input and than pack them
2218 // to
TatWai Chong1719b712020-09-25 18:16:40 -07002219 // the corresponding position.
2220 Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
2221 dup_elements_to_segments(kFormatVnH, temp, zm, index);
2222 pack_even_elements(kFormatVnH, zm_idx, temp);
2223
2224 pack_even_elements(kFormatVnH, zn_b, zn);
2225 pack_odd_elements(kFormatVnH, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002226
2227 switch (form_hash_) {
2228 case Hash("smullb_z_zzi_s"):
2229 VIXL_UNIMPLEMENTED();
2230 break;
2231 case Hash("smullt_z_zzi_s"):
2232 VIXL_UNIMPLEMENTED();
2233 break;
2234 case Hash("sqdmullb_z_zzi_s"):
TatWai Chong1719b712020-09-25 18:16:40 -07002235 sqdmull(kFormatVnS, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002236 break;
2237 case Hash("sqdmullt_z_zzi_s"):
TatWai Chong1719b712020-09-25 18:16:40 -07002238 sqdmull(kFormatVnS, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002239 break;
2240 case Hash("umullb_z_zzi_s"):
2241 VIXL_UNIMPLEMENTED();
2242 break;
2243 case Hash("umullt_z_zzi_s"):
2244 VIXL_UNIMPLEMENTED();
2245 break;
2246 default:
2247 VIXL_UNIMPLEMENTED();
2248 }
2249}
2250
2251void Simulator::Simulate_ZdS_ZnS_ZmS_imm(const Instruction* instr) {
2252 SimVRegister& zd = ReadVRegister(instr->GetRd());
2253 USE(zd);
2254 SimVRegister& zn = ReadVRegister(instr->GetRn());
2255 USE(zn);
2256
2257 switch (form_hash_) {
2258 case Hash("mul_z_zzi_s"):
2259 VIXL_UNIMPLEMENTED();
2260 break;
2261 case Hash("sqdmulh_z_zzi_s"):
2262 VIXL_UNIMPLEMENTED();
2263 break;
2264 case Hash("sqrdmulh_z_zzi_s"):
2265 VIXL_UNIMPLEMENTED();
2266 break;
2267 default:
2268 VIXL_UNIMPLEMENTED();
2269 }
2270}
2271
2272void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002273 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002274 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002275 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002276 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002277 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002278
2279 switch (form_hash_) {
2280 case Hash("flogb_z_p_z"):
2281 VIXL_UNIMPLEMENTED();
2282 break;
2283 case Hash("sqabs_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002284 abs(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002285 break;
2286 case Hash("sqneg_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002287 neg(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002288 break;
2289 default:
2290 VIXL_UNIMPLEMENTED();
2291 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002292 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002293}
2294
2295void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell030875c2020-10-21 18:08:05 +01002296 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002297 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002298 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002299 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002300 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell030875c2020-10-21 18:08:05 +01002301 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002302
Martyn Capewell030875c2020-10-21 18:08:05 +01002303 VIXL_ASSERT(form_hash_ == Hash("histcnt_z_p_zz"));
2304 if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
Martyn Capewell710ec6f2020-10-22 16:56:17 +01002305 histogram(vform, result, pg, zn, zm);
Martyn Capewell030875c2020-10-21 18:08:05 +01002306 mov_zeroing(vform, zd, pg, result);
2307 } else {
2308 VIXL_UNIMPLEMENTED();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002309 }
2310}
2311
Martyn Capewell6bf28752020-08-05 11:57:06 +01002312void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002313 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002314 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002315 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002316 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002317 SimVRegister result;
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002318 bool do_bext = false;
2319
Martyn Capewell6bf28752020-08-05 11:57:06 +01002320 switch (form_hash_) {
2321 case Hash("bdep_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002322 bdep(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002323 break;
2324 case Hash("bext_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002325 do_bext = true;
2326 VIXL_FALLTHROUGH();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002327 case Hash("bgrp_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002328 bgrp(vform, zd, zn, zm, do_bext);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002329 break;
2330 case Hash("eorbt_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002331 rotate_elements_right(vform, result, zm, 1);
2332 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2333 mov_alternating(vform, zd, result, 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002334 break;
2335 case Hash("eortb_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002336 rotate_elements_right(vform, result, zm, -1);
2337 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2338 mov_alternating(vform, zd, result, 1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002339 break;
2340 case Hash("mul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002341 mul(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002342 break;
2343 case Hash("smulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002344 smulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002345 break;
2346 case Hash("sqdmulh_z_zz"):
2347 VIXL_UNIMPLEMENTED();
2348 break;
2349 case Hash("sqrdmulh_z_zz"):
2350 VIXL_UNIMPLEMENTED();
2351 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002352 case Hash("umulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002353 umulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002354 break;
2355 default:
2356 VIXL_UNIMPLEMENTED();
2357 }
2358}
2359
2360void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002361 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002362 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002363 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002364 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002365
2366 SimVRegister zm_b, zm_t;
TatWai Chong236e7ae2020-09-13 14:55:04 -07002367 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2368 pack_even_elements(vform_half, zm_b, zm);
2369 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002370
2371 switch (form_hash_) {
2372 case Hash("saddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002373 saddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002374 break;
2375 case Hash("saddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002376 saddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002377 break;
2378 case Hash("ssubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002379 ssubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002380 break;
2381 case Hash("ssubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002382 ssubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002383 break;
2384 case Hash("uaddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002385 uaddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002386 break;
2387 case Hash("uaddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002388 uaddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002389 break;
2390 case Hash("usubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002391 usubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002392 break;
2393 case Hash("usubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002394 usubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002395 break;
2396 default:
2397 VIXL_UNIMPLEMENTED();
2398 }
2399}
2400
2401void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2402 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002403 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell78743b62020-09-09 11:08:57 +01002404
2405 std::pair<int, int> shift_and_lane_size =
2406 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2407 int lane_size = shift_and_lane_size.second;
2408 VIXL_ASSERT((lane_size >= 0) &&
2409 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2410 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2411 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002412
2413 switch (form_hash_) {
2414 case Hash("sli_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002415 // Shift distance is computed differently for left shifts. Convert the
2416 // result.
2417 shift_dist = (8 << lane_size) - shift_dist;
2418 sli(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002419 break;
2420 case Hash("sri_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002421 sri(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002422 break;
2423 default:
2424 VIXL_UNIMPLEMENTED();
2425 }
2426}
2427
Martyn Capewellea9b4072020-10-09 11:25:26 +01002428void Simulator::SimulateSVENarrow(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002429 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002430 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellb5636e52020-09-17 11:21:29 +01002431 SimVRegister result;
2432
2433 std::pair<int, int> shift_and_lane_size =
2434 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2435 int lane_size = shift_and_lane_size.second;
2436 VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2437 (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2438 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewellea9b4072020-10-09 11:25:26 +01002439 int right_shift_dist = shift_and_lane_size.first;
Martyn Capewellb5636e52020-09-17 11:21:29 +01002440 bool top = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002441
2442 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002443 case Hash("sqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002444 top = true;
2445 VIXL_FALLTHROUGH();
2446 case Hash("sqxtnb_z_zz"):
2447 sqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002448 break;
2449 case Hash("sqxtunt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002450 top = true;
2451 VIXL_FALLTHROUGH();
2452 case Hash("sqxtunb_z_zz"):
2453 sqxtun(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002454 break;
2455 case Hash("uqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002456 top = true;
2457 VIXL_FALLTHROUGH();
2458 case Hash("uqxtnb_z_zz"):
2459 uqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002460 break;
Martyn Capewellea9b4072020-10-09 11:25:26 +01002461 case Hash("rshrnt_z_zi"):
2462 top = true;
2463 VIXL_FALLTHROUGH();
2464 case Hash("rshrnb_z_zi"):
2465 rshrn(vform, result, zn, right_shift_dist);
2466 break;
2467 case Hash("shrnt_z_zi"):
2468 top = true;
2469 VIXL_FALLTHROUGH();
2470 case Hash("shrnb_z_zi"):
2471 shrn(vform, result, zn, right_shift_dist);
2472 break;
2473 case Hash("sqrshrnt_z_zi"):
2474 top = true;
2475 VIXL_FALLTHROUGH();
2476 case Hash("sqrshrnb_z_zi"):
2477 sqrshrn(vform, result, zn, right_shift_dist);
2478 break;
2479 case Hash("sqrshrunt_z_zi"):
2480 top = true;
2481 VIXL_FALLTHROUGH();
2482 case Hash("sqrshrunb_z_zi"):
2483 sqrshrun(vform, result, zn, right_shift_dist);
2484 break;
2485 case Hash("sqshrnt_z_zi"):
2486 top = true;
2487 VIXL_FALLTHROUGH();
2488 case Hash("sqshrnb_z_zi"):
2489 sqshrn(vform, result, zn, right_shift_dist);
2490 break;
2491 case Hash("sqshrunt_z_zi"):
2492 top = true;
2493 VIXL_FALLTHROUGH();
2494 case Hash("sqshrunb_z_zi"):
2495 sqshrun(vform, result, zn, right_shift_dist);
2496 break;
2497 case Hash("uqrshrnt_z_zi"):
2498 top = true;
2499 VIXL_FALLTHROUGH();
2500 case Hash("uqrshrnb_z_zi"):
2501 uqrshrn(vform, result, zn, right_shift_dist);
2502 break;
2503 case Hash("uqshrnt_z_zi"):
2504 top = true;
2505 VIXL_FALLTHROUGH();
2506 case Hash("uqshrnb_z_zi"):
2507 uqshrn(vform, result, zn, right_shift_dist);
2508 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002509 default:
2510 VIXL_UNIMPLEMENTED();
2511 }
Martyn Capewellb5636e52020-09-17 11:21:29 +01002512
2513 if (top) {
2514 // Keep even elements, replace odd elements with the results.
2515 xtn(vform, zd, zd);
2516 zip1(vform, zd, zd, result);
2517 } else {
2518 // Zero odd elements, replace even elements with the results.
2519 SimVRegister zero;
2520 zero.Clear();
2521 zip1(vform, zd, result, zero);
2522 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002523}
2524
Martyn Capewellc7275e62020-09-24 14:06:07 +01002525void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
Martyn Capewella2d7fbb2020-09-18 18:22:54 +01002526 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002527 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002528 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002529 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002530 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2531
2532 // Construct temporary registers containing the even (bottom) and odd (top)
2533 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002534 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2535 pack_even_elements(vform_half, zn_b, zn);
2536 pack_even_elements(vform_half, zm_b, zm);
2537 pack_odd_elements(vform_half, zn_t, zn);
2538 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewellc7275e62020-09-24 14:06:07 +01002539
2540 switch (form_hash_) {
2541 case Hash("sabdlb_z_zz"):
2542 sabdl(vform, zd, zn_b, zm_b);
2543 break;
2544 case Hash("sabdlt_z_zz"):
2545 sabdl(vform, zd, zn_t, zm_t);
2546 break;
2547 case Hash("saddlb_z_zz"):
2548 saddl(vform, zd, zn_b, zm_b);
2549 break;
2550 case Hash("saddlbt_z_zz"):
2551 saddl(vform, zd, zn_b, zm_t);
2552 break;
2553 case Hash("saddlt_z_zz"):
2554 saddl(vform, zd, zn_t, zm_t);
2555 break;
2556 case Hash("ssublb_z_zz"):
2557 ssubl(vform, zd, zn_b, zm_b);
2558 break;
2559 case Hash("ssublbt_z_zz"):
2560 ssubl(vform, zd, zn_b, zm_t);
2561 break;
2562 case Hash("ssublt_z_zz"):
2563 ssubl(vform, zd, zn_t, zm_t);
2564 break;
2565 case Hash("ssubltb_z_zz"):
2566 ssubl(vform, zd, zn_t, zm_b);
2567 break;
2568 case Hash("uabdlb_z_zz"):
2569 uabdl(vform, zd, zn_b, zm_b);
2570 break;
2571 case Hash("uabdlt_z_zz"):
2572 uabdl(vform, zd, zn_t, zm_t);
2573 break;
2574 case Hash("uaddlb_z_zz"):
2575 uaddl(vform, zd, zn_b, zm_b);
2576 break;
2577 case Hash("uaddlt_z_zz"):
2578 uaddl(vform, zd, zn_t, zm_t);
2579 break;
2580 case Hash("usublb_z_zz"):
2581 usubl(vform, zd, zn_b, zm_b);
2582 break;
2583 case Hash("usublt_z_zz"):
2584 usubl(vform, zd, zn_t, zm_t);
2585 break;
Martyn Capewell67d2f822020-10-13 16:39:33 +01002586 case Hash("sabalb_z_zzz"):
2587 sabal(vform, zd, zn_b, zm_b);
2588 break;
2589 case Hash("sabalt_z_zzz"):
2590 sabal(vform, zd, zn_t, zm_t);
2591 break;
2592 case Hash("uabalb_z_zzz"):
2593 uabal(vform, zd, zn_b, zm_b);
2594 break;
2595 case Hash("uabalt_z_zzz"):
2596 uabal(vform, zd, zn_t, zm_t);
2597 break;
Martyn Capewellc7275e62020-09-24 14:06:07 +01002598 default:
2599 VIXL_UNIMPLEMENTED();
2600 }
2601}
2602
TatWai Chong236e7ae2020-09-13 14:55:04 -07002603void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2604 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewellc7275e62020-09-24 14:06:07 +01002605 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002606 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002607 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong236e7ae2020-09-13 14:55:04 -07002608 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2609 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2610 pack_even_elements(vform_half, zn_b, zn);
2611 pack_even_elements(vform_half, zm_b, zm);
2612 pack_odd_elements(vform_half, zn_t, zn);
2613 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002614
2615 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002616 case Hash("pmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002617 // '00' is reserved for Q-sized lane.
2618 if (vform == kFormatVnB) {
2619 VIXL_UNIMPLEMENTED();
2620 }
2621 pmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002622 break;
2623 case Hash("pmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002624 // '00' is reserved for Q-sized lane.
2625 if (vform == kFormatVnB) {
2626 VIXL_UNIMPLEMENTED();
2627 }
2628 pmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002629 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002630 case Hash("smullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002631 smull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002632 break;
2633 case Hash("smullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002634 smull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002635 break;
2636 case Hash("sqdmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002637 sqdmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002638 break;
2639 case Hash("sqdmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002640 sqdmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002641 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002642 case Hash("umullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002643 umull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002644 break;
2645 case Hash("umullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002646 umull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002647 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002648 default:
2649 VIXL_UNIMPLEMENTED();
2650 }
2651}
2652
Martyn Capewell8b9c44b2020-10-14 18:21:42 +01002653void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2654 SimVRegister& zd = ReadVRegister(instr->GetRd());
2655 SimVRegister& zm = ReadVRegister(instr->GetRm());
2656 SimVRegister& zn = ReadVRegister(instr->GetRn());
2657 SimVRegister result;
2658 bool top = false;
2659
2660 VectorFormat vform_src = instr->GetSVEVectorFormat();
2661 if (vform_src == kFormatVnB) {
2662 VIXL_UNIMPLEMENTED();
2663 }
2664 VectorFormat vform = VectorFormatHalfWidth(vform_src);
2665
2666 switch (form_hash_) {
2667 case Hash("addhnt_z_zz"):
2668 top = true;
2669 VIXL_FALLTHROUGH();
2670 case Hash("addhnb_z_zz"):
2671 addhn(vform, result, zn, zm);
2672 break;
2673 case Hash("raddhnt_z_zz"):
2674 top = true;
2675 VIXL_FALLTHROUGH();
2676 case Hash("raddhnb_z_zz"):
2677 raddhn(vform, result, zn, zm);
2678 break;
2679 case Hash("rsubhnt_z_zz"):
2680 top = true;
2681 VIXL_FALLTHROUGH();
2682 case Hash("rsubhnb_z_zz"):
2683 rsubhn(vform, result, zn, zm);
2684 break;
2685 case Hash("subhnt_z_zz"):
2686 top = true;
2687 VIXL_FALLTHROUGH();
2688 case Hash("subhnb_z_zz"):
2689 subhn(vform, result, zn, zm);
2690 break;
2691 default:
2692 VIXL_UNIMPLEMENTED();
2693 }
2694
2695 if (top) {
2696 // Keep even elements, replace odd elements with the results.
2697 xtn(vform, zd, zd);
2698 zip1(vform, zd, zd, result);
2699 } else {
2700 // Zero odd elements, replace even elements with the results.
2701 SimVRegister zero;
2702 zero.Clear();
2703 zip1(vform, zd, result, zero);
2704 }
2705}
2706
Martyn Capewellea9b4072020-10-09 11:25:26 +01002707void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002708 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002709 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell51dcef92020-10-08 16:04:12 +01002710 SimVRegister zn_b, zn_t;
2711
2712 std::pair<int, int> shift_and_lane_size =
2713 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2714 int lane_size = shift_and_lane_size.second;
2715 VIXL_ASSERT((lane_size >= 0) &&
2716 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2717 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2718 int right_shift_dist = shift_and_lane_size.first;
2719 int left_shift_dist = (8 << lane_size) - right_shift_dist;
2720
2721 // Construct temporary registers containing the even (bottom) and odd (top)
2722 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002723 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2724 pack_even_elements(vform_half, zn_b, zn);
2725 pack_odd_elements(vform_half, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002726
2727 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002728 case Hash("sshllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002729 sshll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002730 break;
2731 case Hash("sshllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002732 sshll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002733 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002734 case Hash("ushllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002735 ushll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002736 break;
2737 case Hash("ushllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002738 ushll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002739 break;
2740 default:
2741 VIXL_UNIMPLEMENTED();
2742 }
2743}
2744
2745void Simulator::Simulate_ZdaD_ZnD_ZmD_imm(const Instruction* instr) {
2746 SimVRegister& zda = ReadVRegister(instr->GetRd());
2747 USE(zda);
2748 SimVRegister& zn = ReadVRegister(instr->GetRn());
2749 USE(zn);
2750
2751 switch (form_hash_) {
2752 case Hash("mla_z_zzzi_d"):
2753 VIXL_UNIMPLEMENTED();
2754 break;
2755 case Hash("mls_z_zzzi_d"):
2756 VIXL_UNIMPLEMENTED();
2757 break;
2758 case Hash("sqrdmlah_z_zzzi_d"):
2759 VIXL_UNIMPLEMENTED();
2760 break;
2761 case Hash("sqrdmlsh_z_zzzi_d"):
2762 VIXL_UNIMPLEMENTED();
2763 break;
2764 default:
2765 VIXL_UNIMPLEMENTED();
2766 }
2767}
2768
Martyn Capewell6bf28752020-08-05 11:57:06 +01002769void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2770 SimVRegister& zda = ReadVRegister(instr->GetRd());
2771 USE(zda);
2772 SimVRegister& zn = ReadVRegister(instr->GetRn());
2773 USE(zn);
2774
2775 switch (form_hash_) {
2776 case Hash("smlalb_z_zzzi_d"):
2777 VIXL_UNIMPLEMENTED();
2778 break;
2779 case Hash("smlalt_z_zzzi_d"):
2780 VIXL_UNIMPLEMENTED();
2781 break;
2782 case Hash("smlslb_z_zzzi_d"):
2783 VIXL_UNIMPLEMENTED();
2784 break;
2785 case Hash("smlslt_z_zzzi_d"):
2786 VIXL_UNIMPLEMENTED();
2787 break;
2788 case Hash("sqdmlalb_z_zzzi_d"):
2789 VIXL_UNIMPLEMENTED();
2790 break;
2791 case Hash("sqdmlalt_z_zzzi_d"):
2792 VIXL_UNIMPLEMENTED();
2793 break;
2794 case Hash("sqdmlslb_z_zzzi_d"):
2795 VIXL_UNIMPLEMENTED();
2796 break;
2797 case Hash("sqdmlslt_z_zzzi_d"):
2798 VIXL_UNIMPLEMENTED();
2799 break;
2800 case Hash("umlalb_z_zzzi_d"):
2801 VIXL_UNIMPLEMENTED();
2802 break;
2803 case Hash("umlalt_z_zzzi_d"):
2804 VIXL_UNIMPLEMENTED();
2805 break;
2806 case Hash("umlslb_z_zzzi_d"):
2807 VIXL_UNIMPLEMENTED();
2808 break;
2809 case Hash("umlslt_z_zzzi_d"):
2810 VIXL_UNIMPLEMENTED();
2811 break;
2812 default:
2813 VIXL_UNIMPLEMENTED();
2814 }
2815}
2816
2817void Simulator::Simulate_ZdaH_ZnH_ZmH_imm(const Instruction* instr) {
2818 SimVRegister& zda = ReadVRegister(instr->GetRd());
2819 USE(zda);
2820 SimVRegister& zn = ReadVRegister(instr->GetRn());
2821 USE(zn);
2822
2823 switch (form_hash_) {
2824 case Hash("mla_z_zzzi_h"):
2825 VIXL_UNIMPLEMENTED();
2826 break;
2827 case Hash("mls_z_zzzi_h"):
2828 VIXL_UNIMPLEMENTED();
2829 break;
2830 case Hash("sqrdmlah_z_zzzi_h"):
2831 VIXL_UNIMPLEMENTED();
2832 break;
2833 case Hash("sqrdmlsh_z_zzzi_h"):
2834 VIXL_UNIMPLEMENTED();
2835 break;
2836 default:
2837 VIXL_UNIMPLEMENTED();
2838 }
2839}
2840
2841void Simulator::Simulate_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr) {
2842 SimVRegister& zda = ReadVRegister(instr->GetRd());
2843 USE(zda);
2844 SimVRegister& zn = ReadVRegister(instr->GetRn());
2845 USE(zn);
2846
2847 switch (form_hash_) {
2848 case Hash("cmla_z_zzzi_h"):
2849 VIXL_UNIMPLEMENTED();
2850 break;
2851 case Hash("sqrdcmlah_z_zzzi_h"):
2852 VIXL_UNIMPLEMENTED();
2853 break;
2854 default:
2855 VIXL_UNIMPLEMENTED();
2856 }
2857}
2858
Martyn Capewell6bf28752020-08-05 11:57:06 +01002859void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2860 SimVRegister& zda = ReadVRegister(instr->GetRd());
2861 USE(zda);
2862 SimVRegister& zm = ReadVRegister(instr->GetRm());
2863 USE(zm);
2864 SimVRegister& zn = ReadVRegister(instr->GetRn());
2865 USE(zn);
2866
2867 switch (form_hash_) {
2868 case Hash("fmlalb_z_zzz"):
2869 VIXL_UNIMPLEMENTED();
2870 break;
2871 case Hash("fmlalt_z_zzz"):
2872 VIXL_UNIMPLEMENTED();
2873 break;
2874 case Hash("fmlslb_z_zzz"):
2875 VIXL_UNIMPLEMENTED();
2876 break;
2877 case Hash("fmlslt_z_zzz"):
2878 VIXL_UNIMPLEMENTED();
2879 break;
2880 default:
2881 VIXL_UNIMPLEMENTED();
2882 }
2883}
2884
2885void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2886 SimVRegister& zda = ReadVRegister(instr->GetRd());
2887 USE(zda);
2888 SimVRegister& zm = ReadVRegister(instr->GetRm());
2889 USE(zm);
2890 SimVRegister& zn = ReadVRegister(instr->GetRn());
2891 USE(zn);
2892
2893 switch (form_hash_) {
2894 case Hash("fmlalb_z_zzzi_s"):
2895 VIXL_UNIMPLEMENTED();
2896 break;
2897 case Hash("fmlalt_z_zzzi_s"):
2898 VIXL_UNIMPLEMENTED();
2899 break;
2900 case Hash("fmlslb_z_zzzi_s"):
2901 VIXL_UNIMPLEMENTED();
2902 break;
2903 case Hash("fmlslt_z_zzzi_s"):
2904 VIXL_UNIMPLEMENTED();
2905 break;
2906 case Hash("smlalb_z_zzzi_s"):
2907 VIXL_UNIMPLEMENTED();
2908 break;
2909 case Hash("smlalt_z_zzzi_s"):
2910 VIXL_UNIMPLEMENTED();
2911 break;
2912 case Hash("smlslb_z_zzzi_s"):
2913 VIXL_UNIMPLEMENTED();
2914 break;
2915 case Hash("smlslt_z_zzzi_s"):
2916 VIXL_UNIMPLEMENTED();
2917 break;
2918 case Hash("sqdmlalb_z_zzzi_s"):
2919 VIXL_UNIMPLEMENTED();
2920 break;
2921 case Hash("sqdmlalt_z_zzzi_s"):
2922 VIXL_UNIMPLEMENTED();
2923 break;
2924 case Hash("sqdmlslb_z_zzzi_s"):
2925 VIXL_UNIMPLEMENTED();
2926 break;
2927 case Hash("sqdmlslt_z_zzzi_s"):
2928 VIXL_UNIMPLEMENTED();
2929 break;
2930 case Hash("umlalb_z_zzzi_s"):
2931 VIXL_UNIMPLEMENTED();
2932 break;
2933 case Hash("umlalt_z_zzzi_s"):
2934 VIXL_UNIMPLEMENTED();
2935 break;
2936 case Hash("umlslb_z_zzzi_s"):
2937 VIXL_UNIMPLEMENTED();
2938 break;
2939 case Hash("umlslt_z_zzzi_s"):
2940 VIXL_UNIMPLEMENTED();
2941 break;
2942 default:
2943 VIXL_UNIMPLEMENTED();
2944 }
2945}
2946
2947void Simulator::Simulate_ZdaS_ZnS_ZmS_imm(const Instruction* instr) {
2948 SimVRegister& zda = ReadVRegister(instr->GetRd());
2949 USE(zda);
2950 SimVRegister& zn = ReadVRegister(instr->GetRn());
2951 USE(zn);
2952
2953 switch (form_hash_) {
2954 case Hash("mla_z_zzzi_s"):
2955 VIXL_UNIMPLEMENTED();
2956 break;
2957 case Hash("mls_z_zzzi_s"):
2958 VIXL_UNIMPLEMENTED();
2959 break;
2960 case Hash("sqrdmlah_z_zzzi_s"):
2961 VIXL_UNIMPLEMENTED();
2962 break;
2963 case Hash("sqrdmlsh_z_zzzi_s"):
2964 VIXL_UNIMPLEMENTED();
2965 break;
2966 default:
2967 VIXL_UNIMPLEMENTED();
2968 }
2969}
2970
2971void Simulator::Simulate_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr) {
2972 SimVRegister& zda = ReadVRegister(instr->GetRd());
2973 USE(zda);
2974 SimVRegister& zn = ReadVRegister(instr->GetRn());
2975 USE(zn);
2976
2977 switch (form_hash_) {
2978 case Hash("cmla_z_zzzi_s"):
2979 VIXL_UNIMPLEMENTED();
2980 break;
2981 case Hash("sqrdcmlah_z_zzzi_s"):
2982 VIXL_UNIMPLEMENTED();
2983 break;
2984 default:
2985 VIXL_UNIMPLEMENTED();
2986 }
2987}
2988
2989void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
TatWai Chong602aa122020-10-05 16:28:27 -07002990 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002991 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002992 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002993 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong602aa122020-10-05 16:28:27 -07002994 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002995
2996 switch (form_hash_) {
2997 case Hash("sadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002998 sadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002999 break;
3000 case Hash("uadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07003001 uadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003002 break;
3003 default:
3004 VIXL_UNIMPLEMENTED();
3005 }
TatWai Chong602aa122020-10-05 16:28:27 -07003006 mov_merging(vform, zda, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003007}
3008
Martyn Capewellc4b56bb2020-10-14 15:45:14 +01003009void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
3010 VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
3011 SimVRegister& zda = ReadVRegister(instr->GetRd());
3012 SimVRegister& zm = ReadVRegister(instr->GetRm());
3013 SimVRegister& zn = ReadVRegister(instr->GetRn());
3014
3015 SimVRegister not_zn;
3016 not_(vform, not_zn, zn);
3017
3018 switch (form_hash_) {
3019 case Hash("adclb_z_zzz"):
3020 adcl(vform, zda, zn, zm, /* top = */ false);
3021 break;
3022 case Hash("adclt_z_zzz"):
3023 adcl(vform, zda, zn, zm, /* top = */ true);
3024 break;
3025 case Hash("sbclb_z_zzz"):
3026 adcl(vform, zda, not_zn, zm, /* top = */ false);
3027 break;
3028 case Hash("sbclt_z_zzz"):
3029 adcl(vform, zda, not_zn, zm, /* top = */ true);
3030 break;
3031 default:
3032 VIXL_UNIMPLEMENTED();
3033 }
3034}
3035
Martyn Capewell6bf28752020-08-05 11:57:06 +01003036void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewelleb37ef32020-09-09 16:46:41 +01003037 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003038 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003039 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003040 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003041
3042 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003043 case Hash("saba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01003044 saba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003045 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003046 case Hash("sqrdmlah_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07003047 sqrdmlah(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003048 break;
3049 case Hash("sqrdmlsh_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07003050 sqrdmlsh(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003051 break;
3052 case Hash("uaba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01003053 uaba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003054 break;
3055 default:
3056 VIXL_UNIMPLEMENTED();
3057 }
3058}
3059
3060void Simulator::Simulate_ZdaT_ZnT_ZmT_const(const Instruction* instr) {
3061 SimVRegister& zda = ReadVRegister(instr->GetRd());
3062 USE(zda);
3063 SimVRegister& zm = ReadVRegister(instr->GetRm());
3064 USE(zm);
3065 SimVRegister& zn = ReadVRegister(instr->GetRn());
3066 USE(zn);
3067
3068 switch (form_hash_) {
3069 case Hash("cmla_z_zzz"):
3070 VIXL_UNIMPLEMENTED();
3071 break;
3072 case Hash("sqrdcmlah_z_zzz"):
3073 VIXL_UNIMPLEMENTED();
3074 break;
3075 default:
3076 VIXL_UNIMPLEMENTED();
3077 }
3078}
3079
3080void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003081 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003082 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003083
3084 std::pair<int, int> shift_and_lane_size =
3085 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3086 int lane_size = shift_and_lane_size.second;
3087 VIXL_ASSERT((lane_size >= 0) &&
3088 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3089 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3090 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003091
3092 switch (form_hash_) {
3093 case Hash("srsra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003094 srsra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003095 break;
3096 case Hash("ssra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003097 ssra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003098 break;
3099 case Hash("ursra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003100 ursra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003101 break;
3102 case Hash("usra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003103 usra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003104 break;
3105 default:
3106 VIXL_UNIMPLEMENTED();
3107 }
3108}
3109
3110void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
Martyn Capewell4a454b42020-11-19 18:18:10 +00003111 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003112 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003113 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003114 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell4a454b42020-11-19 18:18:10 +00003115
3116 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
3117 VectorFormat vform_half = VectorFormatHalfWidth(vform);
3118 pack_even_elements(vform_half, zn_b, zn);
3119 pack_even_elements(vform_half, zm_b, zm);
3120 pack_odd_elements(vform_half, zn_t, zn);
3121 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003122
3123 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003124 case Hash("smlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003125 smlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003126 break;
3127 case Hash("smlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003128 smlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003129 break;
3130 case Hash("smlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003131 smlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003132 break;
3133 case Hash("smlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003134 smlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003135 break;
3136 case Hash("sqdmlalb_z_zzz"):
3137 VIXL_UNIMPLEMENTED();
3138 break;
3139 case Hash("sqdmlalbt_z_zzz"):
3140 VIXL_UNIMPLEMENTED();
3141 break;
3142 case Hash("sqdmlalt_z_zzz"):
3143 VIXL_UNIMPLEMENTED();
3144 break;
3145 case Hash("sqdmlslb_z_zzz"):
3146 VIXL_UNIMPLEMENTED();
3147 break;
3148 case Hash("sqdmlslbt_z_zzz"):
3149 VIXL_UNIMPLEMENTED();
3150 break;
3151 case Hash("sqdmlslt_z_zzz"):
3152 VIXL_UNIMPLEMENTED();
3153 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003154 case Hash("umlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003155 umlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003156 break;
3157 case Hash("umlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003158 umlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003159 break;
3160 case Hash("umlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003161 umlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003162 break;
3163 case Hash("umlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003164 umlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003165 break;
3166 default:
3167 VIXL_UNIMPLEMENTED();
3168 }
3169}
3170
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003171void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
Martyn Capewellf4da2202020-11-03 17:42:57 +00003172 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003173 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003174 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellf4da2202020-11-03 17:42:57 +00003175 int rot = instr->ExtractBits(11, 10) * 90;
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003176 unsigned zm_code = instr->GetRm();
3177 int index = -1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003178
3179 switch (form_hash_) {
3180 case Hash("cdot_z_zzz"):
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003181 // Nothing to do.
3182 break;
3183 case Hash("cdot_z_zzzi_s"):
3184 index = zm_code >> 3;
3185 zm_code &= 0x7;
3186 break;
3187 case Hash("cdot_z_zzzi_d"):
3188 index = zm_code >> 4;
3189 zm_code &= 0xf;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003190 break;
3191 default:
3192 VIXL_UNIMPLEMENTED();
3193 }
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003194
3195 SimVRegister temp;
3196 SimVRegister& zm = ReadVRegister(zm_code);
3197 if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3198 cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003199}
3200
Martyn Capewellb1b95782020-10-23 15:59:49 +01003201void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3202 VectorFormat vform = kFormatVnD;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003203 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003204 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellb1b95782020-10-23 15:59:49 +01003205 SimVRegister& zk = ReadVRegister(instr->GetRn());
3206 SimVRegister temp;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003207
3208 switch (form_hash_) {
3209 case Hash("bcax_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003210 bic(vform, temp, zm, zk);
3211 eor(vform, zdn, temp, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003212 break;
3213 case Hash("bsl1n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003214 not_(vform, temp, zdn);
3215 bsl(vform, zdn, zk, temp, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003216 break;
3217 case Hash("bsl2n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003218 not_(vform, temp, zm);
3219 bsl(vform, zdn, zk, zdn, temp);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003220 break;
3221 case Hash("bsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003222 bsl(vform, zdn, zk, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003223 break;
3224 case Hash("eor3_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003225 eor(vform, temp, zdn, zm);
3226 eor(vform, zdn, temp, zk);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003227 break;
3228 case Hash("nbsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003229 bsl(vform, zdn, zk, zdn, zm);
3230 not_(vform, zdn, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003231 break;
3232 default:
3233 VIXL_UNIMPLEMENTED();
3234 }
3235}
3236
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003237void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3238 VectorFormat vform = instr->GetSVEVectorFormat();
3239 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3240 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3241 SimVRegister& zm = ReadVRegister(instr->GetRn());
3242 SimVRegister result;
3243
3244 switch (form_hash_) {
3245 case Hash("shadd_z_p_zz"):
3246 add(vform, result, zdn, zm).Halve(vform);
3247 break;
3248 case Hash("shsub_z_p_zz"):
3249 sub(vform, result, zdn, zm).Halve(vform);
3250 break;
3251 case Hash("shsubr_z_p_zz"):
3252 sub(vform, result, zm, zdn).Halve(vform);
3253 break;
3254 case Hash("srhadd_z_p_zz"):
3255 add(vform, result, zdn, zm).Halve(vform).Round(vform);
3256 break;
3257 case Hash("uhadd_z_p_zz"):
3258 add(vform, result, zdn, zm).Uhalve(vform);
3259 break;
3260 case Hash("uhsub_z_p_zz"):
3261 sub(vform, result, zdn, zm).Uhalve(vform);
3262 break;
3263 case Hash("uhsubr_z_p_zz"):
3264 sub(vform, result, zm, zdn).Uhalve(vform);
3265 break;
3266 case Hash("urhadd_z_p_zz"):
3267 add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3268 break;
3269 default:
3270 VIXL_UNIMPLEMENTED();
Martyn Capewell9b532192020-09-15 16:20:11 +01003271 break;
3272 }
3273 mov_merging(vform, zdn, pg, result);
3274}
3275
3276void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3277 VectorFormat vform = instr->GetSVEVectorFormat();
3278 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3279 SimVRegister& zm = ReadVRegister(instr->GetRn());
3280 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3281 SimVRegister result;
3282
3283 switch (form_hash_) {
3284 case Hash("sqadd_z_p_zz"):
3285 add(vform, result, zdn, zm).SignedSaturate(vform);
3286 break;
3287 case Hash("sqsub_z_p_zz"):
3288 sub(vform, result, zdn, zm).SignedSaturate(vform);
3289 break;
3290 case Hash("sqsubr_z_p_zz"):
3291 sub(vform, result, zm, zdn).SignedSaturate(vform);
3292 break;
3293 case Hash("suqadd_z_p_zz"):
3294 suqadd(vform, result, zdn, zm);
3295 break;
3296 case Hash("uqadd_z_p_zz"):
3297 add(vform, result, zdn, zm).UnsignedSaturate(vform);
3298 break;
3299 case Hash("uqsub_z_p_zz"):
3300 sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3301 break;
3302 case Hash("uqsubr_z_p_zz"):
3303 sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3304 break;
3305 case Hash("usqadd_z_p_zz"):
3306 usqadd(vform, result, zdn, zm);
3307 break;
3308 default:
3309 VIXL_UNIMPLEMENTED();
3310 break;
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003311 }
3312 mov_merging(vform, zdn, pg, result);
3313}
3314
Martyn Capewellfa1e2112020-09-16 16:53:09 +01003315void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3316 VectorFormat vform = instr->GetSVEVectorFormat();
3317 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3318 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3319 SimVRegister& zm = ReadVRegister(instr->GetRn());
3320 SimVRegister result;
3321
3322 switch (form_hash_) {
3323 case Hash("addp_z_p_zz"):
3324 addp(vform, result, zdn, zm);
3325 break;
3326 case Hash("smaxp_z_p_zz"):
3327 smaxp(vform, result, zdn, zm);
3328 break;
3329 case Hash("sminp_z_p_zz"):
3330 sminp(vform, result, zdn, zm);
3331 break;
3332 case Hash("umaxp_z_p_zz"):
3333 umaxp(vform, result, zdn, zm);
3334 break;
3335 case Hash("uminp_z_p_zz"):
3336 uminp(vform, result, zdn, zm);
3337 break;
3338 default:
3339 VIXL_UNIMPLEMENTED();
3340 break;
3341 }
3342 mov_merging(vform, zdn, pg, result);
3343}
3344
Martyn Capewell6bf28752020-08-05 11:57:06 +01003345void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3346 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3347 USE(pg);
3348 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3349 USE(zdn);
3350 SimVRegister& zm = ReadVRegister(instr->GetRn());
3351 USE(zm);
3352
3353 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003354 case Hash("faddp_z_p_zz"):
3355 VIXL_UNIMPLEMENTED();
3356 break;
3357 case Hash("fmaxnmp_z_p_zz"):
3358 VIXL_UNIMPLEMENTED();
3359 break;
3360 case Hash("fmaxp_z_p_zz"):
3361 VIXL_UNIMPLEMENTED();
3362 break;
3363 case Hash("fminnmp_z_p_zz"):
3364 VIXL_UNIMPLEMENTED();
3365 break;
3366 case Hash("fminp_z_p_zz"):
3367 VIXL_UNIMPLEMENTED();
3368 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003369 case Hash("sqrshl_z_p_zz"):
3370 VIXL_UNIMPLEMENTED();
3371 break;
3372 case Hash("sqrshlr_z_p_zz"):
3373 VIXL_UNIMPLEMENTED();
3374 break;
3375 case Hash("sqshl_z_p_zz"):
3376 VIXL_UNIMPLEMENTED();
3377 break;
3378 case Hash("sqshlr_z_p_zz"):
3379 VIXL_UNIMPLEMENTED();
3380 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003381 case Hash("srshl_z_p_zz"):
3382 VIXL_UNIMPLEMENTED();
3383 break;
3384 case Hash("srshlr_z_p_zz"):
3385 VIXL_UNIMPLEMENTED();
3386 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003387 case Hash("uqrshl_z_p_zz"):
3388 VIXL_UNIMPLEMENTED();
3389 break;
3390 case Hash("uqrshlr_z_p_zz"):
3391 VIXL_UNIMPLEMENTED();
3392 break;
3393 case Hash("uqshl_z_p_zz"):
3394 VIXL_UNIMPLEMENTED();
3395 break;
3396 case Hash("uqshlr_z_p_zz"):
3397 VIXL_UNIMPLEMENTED();
3398 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003399 case Hash("urshl_z_p_zz"):
3400 VIXL_UNIMPLEMENTED();
3401 break;
3402 case Hash("urshlr_z_p_zz"):
3403 VIXL_UNIMPLEMENTED();
3404 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003405 default:
3406 VIXL_UNIMPLEMENTED();
3407 }
3408}
3409
3410void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3411 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003412 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003413
3414 std::pair<int, int> shift_and_lane_size =
3415 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3416 unsigned lane_size = shift_and_lane_size.second;
3417 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3418 int right_shift_dist = shift_and_lane_size.first;
3419 int left_shift_dist = (8 << lane_size) - right_shift_dist;
3420 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003421
3422 switch (form_hash_) {
3423 case Hash("sqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003424 sqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003425 break;
3426 case Hash("sqshlu_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003427 sqshlu(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003428 break;
3429 case Hash("srshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003430 sshr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003431 break;
3432 case Hash("uqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003433 uqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003434 break;
3435 case Hash("urshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003436 ushr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003437 break;
3438 default:
3439 VIXL_UNIMPLEMENTED();
3440 }
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003441 mov_merging(vform, zdn, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003442}
3443
Martyn Capewell97ca8062020-10-23 14:45:14 +01003444void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3445 VIXL_ASSERT(form_hash_ == Hash("xar_z_zzi"));
3446
3447 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3448 SimVRegister& zm = ReadVRegister(instr->GetRn());
3449
3450 std::pair<int, int> shift_and_lane_size =
3451 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3452 unsigned lane_size = shift_and_lane_size.second;
3453 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3454 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3455 int shift_dist = shift_and_lane_size.first;
Martyn Capewellb1b95782020-10-23 15:59:49 +01003456 eor(vform, zdn, zdn, zm);
Martyn Capewell97ca8062020-10-23 14:45:14 +01003457 ror(vform, zdn, zdn, shift_dist);
3458}
3459
Martyn Capewell6bf28752020-08-05 11:57:06 +01003460void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
Martyn Capewell819dcf92020-10-20 16:07:09 +01003461 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003462 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003463 SimVRegister& zm = ReadVRegister(instr->GetRn());
Martyn Capewell819dcf92020-10-20 16:07:09 +01003464 int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003465
3466 switch (form_hash_) {
3467 case Hash("cadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003468 cadd(vform, zdn, zdn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003469 break;
3470 case Hash("sqcadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003471 cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003472 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003473 default:
3474 VIXL_UNIMPLEMENTED();
3475 }
3476}
3477
3478void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3479 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003480 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003481 uint64_t xm = ReadXRegister(instr->GetRm());
3482
3483 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3484 int msize = -1;
3485 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003486
3487 switch (form_hash_) {
3488 case Hash("ldnt1b_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003489 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003490 break;
3491 case Hash("ldnt1d_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003492 msize = 3;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003493 break;
3494 case Hash("ldnt1h_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003495 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003496 break;
3497 case Hash("ldnt1sb_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003498 msize = 0;
3499 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003500 break;
3501 case Hash("ldnt1sh_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003502 msize = 1;
3503 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003504 break;
3505 case Hash("ldnt1sw_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003506 msize = 2;
3507 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003508 break;
3509 case Hash("ldnt1w_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003510 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003511 break;
3512 default:
3513 VIXL_UNIMPLEMENTED();
3514 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003515 addr.SetMsizeInBytesLog2(msize);
3516 SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003517}
3518
3519void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3520 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003521 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003522 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003523
Martyn Capewell1ac83572020-11-11 16:15:58 +00003524 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3525 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_d_64_unscaled")) ||
3526 (form_hash_ == Hash("stnt1d_z_p_ar_d_64_unscaled")) ||
3527 (form_hash_ == Hash("stnt1h_z_p_ar_d_64_unscaled")) ||
3528 (form_hash_ == Hash("stnt1w_z_p_ar_d_64_unscaled")));
3529
3530 addr.SetMsizeInBytesLog2(
3531 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3532 SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003533}
3534
3535void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3536 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003537 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003538 uint64_t xm = ReadXRegister(instr->GetRm());
3539
3540 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3541 int msize = -1;
3542 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003543
3544 switch (form_hash_) {
3545 case Hash("ldnt1b_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003546 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003547 break;
3548 case Hash("ldnt1h_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003549 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003550 break;
3551 case Hash("ldnt1sb_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003552 msize = 0;
3553 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003554 break;
3555 case Hash("ldnt1sh_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003556 msize = 1;
3557 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003558 break;
3559 case Hash("ldnt1w_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003560 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003561 break;
3562 default:
3563 VIXL_UNIMPLEMENTED();
3564 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003565 addr.SetMsizeInBytesLog2(msize);
3566 SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003567}
3568
3569void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3570 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003571 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003572 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003573
Martyn Capewell1ac83572020-11-11 16:15:58 +00003574 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3575 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_s_x32_unscaled")) ||
3576 (form_hash_ == Hash("stnt1h_z_p_ar_s_x32_unscaled")) ||
3577 (form_hash_ == Hash("stnt1w_z_p_ar_s_x32_unscaled")));
3578
3579 addr.SetMsizeInBytesLog2(
3580 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3581 SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003582}
3583
Jacob Bramley18c97bd2019-01-18 16:01:08 +00003584void Simulator::VisitReserved(const Instruction* instr) {
3585 // UDF is the only instruction in this group, and the Decoder is precise here.
3586 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3587
3588 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3589 reinterpret_cast<const void*>(instr),
3590 instr->GetInstructionBits());
3591 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3592}
3593
3594
Alexandre Ramesd3832962016-07-04 15:03:43 +01003595void Simulator::VisitUnimplemented(const Instruction* instr) {
3596 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3597 reinterpret_cast<const void*>(instr),
3598 instr->GetInstructionBits());
3599 VIXL_UNIMPLEMENTED();
3600}
3601
3602
3603void Simulator::VisitUnallocated(const Instruction* instr) {
3604 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3605 reinterpret_cast<const void*>(instr),
3606 instr->GetInstructionBits());
3607 VIXL_UNIMPLEMENTED();
3608}
3609
3610
3611void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3612 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3613 (instr->Mask(PCRelAddressingMask) == ADRP));
3614
3615 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3616}
3617
3618
3619void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3620 switch (instr->Mask(UnconditionalBranchMask)) {
3621 case BL:
3622 WriteLr(instr->GetNextInstruction());
3623 VIXL_FALLTHROUGH();
3624 case B:
3625 WritePc(instr->GetImmPCOffsetTarget());
3626 break;
3627 default:
3628 VIXL_UNREACHABLE();
3629 }
3630}
3631
3632
3633void Simulator::VisitConditionalBranch(const Instruction* instr) {
3634 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3635 if (ConditionPassed(instr->GetConditionBranch())) {
3636 WritePc(instr->GetImmPCOffsetTarget());
3637 }
3638}
3639
Martyn Capewellcb963f72018-10-22 15:25:28 +01003640BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3641 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3642 case BLR:
3643 case BLRAA:
3644 case BLRAB:
3645 case BLRAAZ:
3646 case BLRABZ:
3647 return BranchAndLink;
3648 case BR:
3649 case BRAA:
3650 case BRAB:
3651 case BRAAZ:
3652 case BRABZ:
3653 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3654 !PcIsInGuardedPage()) {
3655 return BranchFromUnguardedOrToIP;
3656 }
3657 return BranchFromGuardedNotToIP;
3658 }
3659 return DefaultBType;
3660}
Alexandre Ramesd3832962016-07-04 15:03:43 +01003661
3662void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003663 bool authenticate = false;
3664 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01003665 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01003666 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003667
3668 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3669 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01003670 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003671 VIXL_FALLTHROUGH();
3672 case BR:
3673 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01003674 break;
3675
3676 case BLRAAZ:
3677 case BLRABZ:
3678 link = true;
3679 VIXL_FALLTHROUGH();
3680 case BRAAZ:
3681 case BRABZ:
3682 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003683 break;
3684
3685 case BLRAA:
3686 case BLRAB:
3687 link = true;
3688 VIXL_FALLTHROUGH();
3689 case BRAA:
3690 case BRAB:
3691 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003692 context = ReadXRegister(instr->GetRd());
3693 break;
3694
3695 case RETAA:
3696 case RETAB:
3697 authenticate = true;
3698 addr = ReadXRegister(kLinkRegCode);
3699 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003700 break;
3701 default:
3702 VIXL_UNREACHABLE();
3703 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003704
3705 if (link) {
3706 WriteLr(instr->GetNextInstruction());
3707 }
3708
3709 if (authenticate) {
3710 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3711 addr = AuthPAC(addr, context, key, kInstructionPointer);
3712
3713 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3714 if (((addr >> error_lsb) & 0x3) != 0x0) {
3715 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3716 }
3717 }
3718
Martyn Capewellcb963f72018-10-22 15:25:28 +01003719 WritePc(Instruction::Cast(addr));
3720 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003721}
3722
3723
3724void Simulator::VisitTestBranch(const Instruction* instr) {
3725 unsigned bit_pos =
3726 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3727 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3728 bool take_branch = false;
3729 switch (instr->Mask(TestBranchMask)) {
3730 case TBZ:
3731 take_branch = bit_zero;
3732 break;
3733 case TBNZ:
3734 take_branch = !bit_zero;
3735 break;
3736 default:
3737 VIXL_UNIMPLEMENTED();
3738 }
3739 if (take_branch) {
3740 WritePc(instr->GetImmPCOffsetTarget());
3741 }
3742}
3743
3744
3745void Simulator::VisitCompareBranch(const Instruction* instr) {
3746 unsigned rt = instr->GetRt();
3747 bool take_branch = false;
3748 switch (instr->Mask(CompareBranchMask)) {
3749 case CBZ_w:
3750 take_branch = (ReadWRegister(rt) == 0);
3751 break;
3752 case CBZ_x:
3753 take_branch = (ReadXRegister(rt) == 0);
3754 break;
3755 case CBNZ_w:
3756 take_branch = (ReadWRegister(rt) != 0);
3757 break;
3758 case CBNZ_x:
3759 take_branch = (ReadXRegister(rt) != 0);
3760 break;
3761 default:
3762 VIXL_UNIMPLEMENTED();
3763 }
3764 if (take_branch) {
3765 WritePc(instr->GetImmPCOffsetTarget());
3766 }
3767}
3768
3769
3770void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3771 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3772 bool set_flags = instr->GetFlagsUpdate();
3773 int64_t new_val = 0;
3774 Instr operation = instr->Mask(AddSubOpMask);
3775
3776 switch (operation) {
3777 case ADD:
3778 case ADDS: {
3779 new_val = AddWithCarry(reg_size,
3780 set_flags,
3781 ReadRegister(reg_size,
3782 instr->GetRn(),
3783 instr->GetRnMode()),
3784 op2);
3785 break;
3786 }
3787 case SUB:
3788 case SUBS: {
3789 new_val = AddWithCarry(reg_size,
3790 set_flags,
3791 ReadRegister(reg_size,
3792 instr->GetRn(),
3793 instr->GetRnMode()),
3794 ~op2,
3795 1);
3796 break;
3797 }
3798 default:
3799 VIXL_UNREACHABLE();
3800 }
3801
3802 WriteRegister(reg_size,
3803 instr->GetRd(),
3804 new_val,
3805 LogRegWrites,
3806 instr->GetRdMode());
3807}
3808
3809
3810void Simulator::VisitAddSubShifted(const Instruction* instr) {
3811 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3812 int64_t op2 = ShiftOperand(reg_size,
3813 ReadRegister(reg_size, instr->GetRm()),
3814 static_cast<Shift>(instr->GetShiftDP()),
3815 instr->GetImmDPShift());
3816 AddSubHelper(instr, op2);
3817}
3818
3819
3820void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3821 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01003822 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003823 AddSubHelper(instr, op2);
3824}
3825
3826
3827void Simulator::VisitAddSubExtended(const Instruction* instr) {
3828 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3829 int64_t op2 = ExtendValue(reg_size,
3830 ReadRegister(reg_size, instr->GetRm()),
3831 static_cast<Extend>(instr->GetExtendMode()),
3832 instr->GetImmExtendShift());
3833 AddSubHelper(instr, op2);
3834}
3835
3836
3837void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3838 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3839 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3840 int64_t new_val;
3841
3842 if ((instr->Mask(AddSubOpMask) == SUB) ||
3843 (instr->Mask(AddSubOpMask) == SUBS)) {
3844 op2 = ~op2;
3845 }
3846
3847 new_val = AddWithCarry(reg_size,
3848 instr->GetFlagsUpdate(),
3849 ReadRegister(reg_size, instr->GetRn()),
3850 op2,
3851 ReadC());
3852
3853 WriteRegister(reg_size, instr->GetRd(), new_val);
3854}
3855
3856
Alexander Gilday2487f142018-11-05 13:07:27 +00003857void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3858 switch (instr->Mask(RotateRightIntoFlagsMask)) {
3859 case RMIF: {
3860 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3861 unsigned shift = instr->GetImmRMIFRotation();
3862 unsigned mask = instr->GetNzcv();
3863 uint64_t rotated = RotateRight(value, shift, kXRegSize);
3864
3865 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3866 break;
3867 }
3868 }
3869}
3870
3871
3872void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3873 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3874 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3875
3876 unsigned sign_bit = (value >> msb) & 1;
3877 unsigned overflow_bit = (value >> (msb + 1)) & 1;
3878 ReadNzcv().SetN(sign_bit);
3879 ReadNzcv().SetZ((value << (31 - msb)) == 0);
3880 ReadNzcv().SetV(sign_bit ^ overflow_bit);
3881}
3882
3883
Alexandre Ramesd3832962016-07-04 15:03:43 +01003884void Simulator::VisitLogicalShifted(const Instruction* instr) {
3885 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3886 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3887 unsigned shift_amount = instr->GetImmDPShift();
3888 int64_t op2 = ShiftOperand(reg_size,
3889 ReadRegister(reg_size, instr->GetRm()),
3890 shift_type,
3891 shift_amount);
3892 if (instr->Mask(NOT) == NOT) {
3893 op2 = ~op2;
3894 }
3895 LogicalHelper(instr, op2);
3896}
3897
3898
3899void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3900 LogicalHelper(instr, instr->GetImmLogical());
3901}
3902
3903
3904void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3905 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3906 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3907 int64_t result = 0;
3908 bool update_flags = false;
3909
3910 // Switch on the logical operation, stripping out the NOT bit, as it has a
3911 // different meaning for logical immediate instructions.
3912 switch (instr->Mask(LogicalOpMask & ~NOT)) {
3913 case ANDS:
3914 update_flags = true;
3915 VIXL_FALLTHROUGH();
3916 case AND:
3917 result = op1 & op2;
3918 break;
3919 case ORR:
3920 result = op1 | op2;
3921 break;
3922 case EOR:
3923 result = op1 ^ op2;
3924 break;
3925 default:
3926 VIXL_UNIMPLEMENTED();
3927 }
3928
3929 if (update_flags) {
3930 ReadNzcv().SetN(CalcNFlag(result, reg_size));
3931 ReadNzcv().SetZ(CalcZFlag(result));
3932 ReadNzcv().SetC(0);
3933 ReadNzcv().SetV(0);
3934 LogSystemRegister(NZCV);
3935 }
3936
3937 WriteRegister(reg_size,
3938 instr->GetRd(),
3939 result,
3940 LogRegWrites,
3941 instr->GetRdMode());
3942}
3943
3944
3945void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3946 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3947 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3948}
3949
3950
3951void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3952 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3953}
3954
3955
3956void Simulator::ConditionalCompareHelper(const Instruction* instr,
3957 int64_t op2) {
3958 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3959 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3960
3961 if (ConditionPassed(instr->GetCondition())) {
3962 // If the condition passes, set the status flags to the result of comparing
3963 // the operands.
3964 if (instr->Mask(ConditionalCompareMask) == CCMP) {
3965 AddWithCarry(reg_size, true, op1, ~op2, 1);
3966 } else {
3967 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3968 AddWithCarry(reg_size, true, op1, op2, 0);
3969 }
3970 } else {
3971 // If the condition fails, set the status flags to the nzcv immediate.
3972 ReadNzcv().SetFlags(instr->GetNzcv());
3973 LogSystemRegister(NZCV);
3974 }
3975}
3976
3977
3978void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3979 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3980 LoadStoreHelper(instr, offset, Offset);
3981}
3982
3983
3984void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3985 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3986}
3987
3988
3989void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3990 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3991}
3992
3993
3994void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3995 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3996}
3997
3998
Alexander Gilday311edf22018-10-29 13:41:41 +00003999template <typename T1, typename T2>
4000void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
4001 unsigned rt = instr->GetRt();
4002 unsigned rn = instr->GetRn();
4003
4004 unsigned element_size = sizeof(T2);
4005 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4006 int offset = instr->GetImmLS();
4007 address += offset;
4008
4009 // Verify that the address is available to the host.
4010 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4011
4012 // Check the alignment of `address`.
4013 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
4014 VIXL_ALIGNMENT_EXCEPTION();
4015 }
4016
4017 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
4018
4019 // Approximate load-acquire by issuing a full barrier after the load.
4020 __sync_synchronize();
4021
Jacob Bramley423e5422019-11-13 19:15:55 +00004022 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00004023}
4024
4025
4026template <typename T>
4027void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
4028 unsigned rt = instr->GetRt();
4029 unsigned rn = instr->GetRn();
4030
4031 unsigned element_size = sizeof(T);
4032 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4033 int offset = instr->GetImmLS();
4034 address += offset;
4035
4036 // Verify that the address is available to the host.
4037 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4038
4039 // Check the alignment of `address`.
4040 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
4041 VIXL_ALIGNMENT_EXCEPTION();
4042 }
4043
4044 // Approximate store-release by issuing a full barrier after the load.
4045 __sync_synchronize();
4046
4047 Memory::Write<T>(address, ReadRegister<T>(rt));
4048
Jacob Bramley423e5422019-11-13 19:15:55 +00004049 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00004050}
4051
4052
4053void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
4054 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
4055 case LDAPURB:
4056 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
4057 break;
4058 case LDAPURH:
4059 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
4060 break;
4061 case LDAPUR_w:
4062 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
4063 break;
4064 case LDAPUR_x:
4065 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
4066 break;
4067 case LDAPURSB_w:
4068 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
4069 break;
4070 case LDAPURSB_x:
4071 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
4072 break;
4073 case LDAPURSH_w:
4074 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
4075 break;
4076 case LDAPURSH_x:
4077 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
4078 break;
4079 case LDAPURSW:
4080 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
4081 break;
4082 case STLURB:
4083 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
4084 break;
4085 case STLURH:
4086 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4087 break;
4088 case STLUR_w:
4089 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4090 break;
4091 case STLUR_x:
4092 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4093 break;
4094 }
4095}
4096
4097
Alexander Gilday75605592018-11-01 09:30:29 +00004098void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4099 unsigned dst = instr->GetRt();
4100 unsigned addr_reg = instr->GetRn();
4101
4102 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4103
4104 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4105 address = AuthPAC(address, 0, key, kDataPointer);
4106
4107 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4108 if (((address >> error_lsb) & 0x3) != 0x0) {
4109 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4110 }
4111
4112
4113 if ((addr_reg == 31) && ((address % 16) != 0)) {
4114 // When the base register is SP the stack pointer is required to be
4115 // quadword aligned prior to the address calculation and write-backs.
4116 // Misalignment will cause a stack alignment fault.
4117 VIXL_ALIGNMENT_EXCEPTION();
4118 }
4119
4120 int64_t offset = instr->GetImmLSPAC();
4121 address += offset;
4122
4123 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4124 // Pre-index mode.
4125 VIXL_ASSERT(offset != 0);
4126 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4127 }
4128
4129 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4130
4131 // Verify that the calculated address is available to the host.
4132 VIXL_ASSERT(address == addr_ptr);
4133
4134 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
4135 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00004136 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00004137}
4138
4139
Alexandre Ramesd3832962016-07-04 15:03:43 +01004140void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4141 Extend ext = static_cast<Extend>(instr->GetExtendMode());
4142 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4143 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4144
4145 int64_t offset =
4146 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4147 LoadStoreHelper(instr, offset, Offset);
4148}
4149
4150
4151void Simulator::LoadStoreHelper(const Instruction* instr,
4152 int64_t offset,
4153 AddrMode addrmode) {
4154 unsigned srcdst = instr->GetRt();
4155 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4156
Jacob Bramley423e5422019-11-13 19:15:55 +00004157 bool rt_is_vreg = false;
4158 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004159 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4160 switch (op) {
4161 case LDRB_w:
4162 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004163 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004164 break;
4165 case LDRH_w:
4166 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004167 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004168 break;
4169 case LDR_w:
4170 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004171 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004172 break;
4173 case LDR_x:
4174 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004175 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004176 break;
4177 case LDRSB_w:
4178 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004179 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004180 break;
4181 case LDRSH_w:
4182 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004183 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004184 break;
4185 case LDRSB_x:
4186 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004187 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004188 break;
4189 case LDRSH_x:
4190 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004191 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004192 break;
4193 case LDRSW_x:
4194 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004195 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004196 break;
4197 case LDR_b:
4198 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004199 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004200 break;
4201 case LDR_h:
4202 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004203 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004204 break;
4205 case LDR_s:
4206 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004207 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004208 break;
4209 case LDR_d:
4210 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004211 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004212 break;
4213 case LDR_q:
4214 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004215 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004216 break;
4217
4218 case STRB_w:
4219 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
4220 break;
4221 case STRH_w:
4222 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
4223 break;
4224 case STR_w:
4225 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
4226 break;
4227 case STR_x:
4228 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
4229 break;
4230 case STR_b:
4231 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004232 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004233 break;
4234 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01004235 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004236 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004237 break;
4238 case STR_s:
4239 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004240 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004241 break;
4242 case STR_d:
4243 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004244 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004245 break;
4246 case STR_q:
4247 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004248 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004249 break;
4250
4251 // Ignore prfm hint instructions.
4252 case PRFM:
4253 break;
4254
4255 default:
4256 VIXL_UNIMPLEMENTED();
4257 }
4258
Jacob Bramley423e5422019-11-13 19:15:55 +00004259 // Print a detailed trace (including the memory address).
4260 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004261 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00004262 unsigned result_size = extend ? extend_to_size : access_size;
4263 PrintRegisterFormat print_format =
4264 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4265 : GetPrintRegisterFormatForSize(result_size);
4266
Alexandre Ramesd3832962016-07-04 15:03:43 +01004267 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004268 if (rt_is_vreg) {
4269 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004270 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004271 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004272 }
4273 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004274 if (rt_is_vreg) {
4275 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004276 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004277 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004278 }
4279 } else {
4280 VIXL_ASSERT(op == PRFM);
4281 }
4282
4283 local_monitor_.MaybeClear();
4284}
4285
4286
4287void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4288 LoadStorePairHelper(instr, Offset);
4289}
4290
4291
4292void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4293 LoadStorePairHelper(instr, PreIndex);
4294}
4295
4296
4297void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4298 LoadStorePairHelper(instr, PostIndex);
4299}
4300
4301
4302void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4303 LoadStorePairHelper(instr, Offset);
4304}
4305
4306
4307void Simulator::LoadStorePairHelper(const Instruction* instr,
4308 AddrMode addrmode) {
4309 unsigned rt = instr->GetRt();
4310 unsigned rt2 = instr->GetRt2();
4311 int element_size = 1 << instr->GetSizeLSPair();
4312 int64_t offset = instr->GetImmLSPair() * element_size;
4313 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4314 uintptr_t address2 = address + element_size;
4315
4316 LoadStorePairOp op =
4317 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4318
4319 // 'rt' and 'rt2' can only be aliased for stores.
4320 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4321
Jacob Bramley423e5422019-11-13 19:15:55 +00004322 bool rt_is_vreg = false;
4323 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004324 switch (op) {
4325 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4326 // will print a more detailed log.
4327 case LDP_w: {
4328 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4329 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
4330 break;
4331 }
4332 case LDP_s: {
4333 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
4334 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004335 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004336 break;
4337 }
4338 case LDP_x: {
4339 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4340 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
4341 break;
4342 }
4343 case LDP_d: {
4344 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
4345 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004346 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004347 break;
4348 }
4349 case LDP_q: {
4350 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
4351 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004352 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004353 break;
4354 }
4355 case LDPSW_x: {
4356 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
4357 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004358 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004359 break;
4360 }
4361 case STP_w: {
4362 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4363 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
4364 break;
4365 }
4366 case STP_s: {
4367 Memory::Write<float>(address, ReadSRegister(rt));
4368 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004369 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004370 break;
4371 }
4372 case STP_x: {
4373 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4374 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
4375 break;
4376 }
4377 case STP_d: {
4378 Memory::Write<double>(address, ReadDRegister(rt));
4379 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004380 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004381 break;
4382 }
4383 case STP_q: {
4384 Memory::Write<qreg_t>(address, ReadQRegister(rt));
4385 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004386 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004387 break;
4388 }
4389 default:
4390 VIXL_UNREACHABLE();
4391 }
4392
Jacob Bramley423e5422019-11-13 19:15:55 +00004393 // Print a detailed trace (including the memory address).
4394 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4395 PrintRegisterFormat print_format =
4396 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4397 : GetPrintRegisterFormatForSize(result_size);
4398
Alexandre Ramesd3832962016-07-04 15:03:43 +01004399 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004400 if (rt_is_vreg) {
4401 LogVRead(rt, print_format, address);
4402 LogVRead(rt2, print_format, address2);
4403 } else if (sign_extend) {
4404 LogExtendingRead(rt, print_format, element_size, address);
4405 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004406 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004407 LogRead(rt, print_format, address);
4408 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004409 }
4410 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004411 if (rt_is_vreg) {
4412 LogVWrite(rt, print_format, address);
4413 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004414 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004415 LogWrite(rt, print_format, address);
4416 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004417 }
4418 }
4419
4420 local_monitor_.MaybeClear();
4421}
4422
4423
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004424template <typename T>
4425void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4426 unsigned rs = instr->GetRs();
4427 unsigned rt = instr->GetRt();
4428 unsigned rn = instr->GetRn();
4429
4430 unsigned element_size = sizeof(T);
4431 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4432
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004433 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4434
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004435 bool is_acquire = instr->ExtractBit(22) == 1;
4436 bool is_release = instr->ExtractBit(15) == 1;
4437
4438 T comparevalue = ReadRegister<T>(rs);
4439 T newvalue = ReadRegister<T>(rt);
4440
4441 // The architecture permits that the data read clears any exclusive monitors
4442 // associated with that location, even if the compare subsequently fails.
4443 local_monitor_.Clear();
4444
4445 T data = Memory::Read<T>(address);
4446 if (is_acquire) {
4447 // Approximate load-acquire by issuing a full barrier after the load.
4448 __sync_synchronize();
4449 }
4450
4451 if (data == comparevalue) {
4452 if (is_release) {
4453 // Approximate store-release by issuing a full barrier before the store.
4454 __sync_synchronize();
4455 }
4456 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00004457 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004458 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004459 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004460 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004461}
4462
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004463
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004464template <typename T>
4465void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4466 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4467 unsigned rs = instr->GetRs();
4468 unsigned rt = instr->GetRt();
4469 unsigned rn = instr->GetRn();
4470
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004471 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004472
4473 unsigned element_size = sizeof(T);
4474 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004475
4476 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4477
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004478 uint64_t address2 = address + element_size;
4479
4480 bool is_acquire = instr->ExtractBit(22) == 1;
4481 bool is_release = instr->ExtractBit(15) == 1;
4482
4483 T comparevalue_high = ReadRegister<T>(rs + 1);
4484 T comparevalue_low = ReadRegister<T>(rs);
4485 T newvalue_high = ReadRegister<T>(rt + 1);
4486 T newvalue_low = ReadRegister<T>(rt);
4487
4488 // The architecture permits that the data read clears any exclusive monitors
4489 // associated with that location, even if the compare subsequently fails.
4490 local_monitor_.Clear();
4491
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004492 T data_low = Memory::Read<T>(address);
4493 T data_high = Memory::Read<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004494
4495 if (is_acquire) {
4496 // Approximate load-acquire by issuing a full barrier after the load.
4497 __sync_synchronize();
4498 }
4499
4500 bool same =
4501 (data_high == comparevalue_high) && (data_low == comparevalue_low);
4502 if (same) {
4503 if (is_release) {
4504 // Approximate store-release by issuing a full barrier before the store.
4505 __sync_synchronize();
4506 }
4507
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004508 Memory::Write<T>(address, newvalue_low);
4509 Memory::Write<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004510 }
4511
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004512 WriteRegister<T>(rs + 1, data_high, NoRegLog);
4513 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004514
Jacob Bramley423e5422019-11-13 19:15:55 +00004515 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004516 LogRead(rs, format, address);
4517 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004518
4519 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004520 LogWrite(rt, format, address);
4521 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004522 }
4523}
4524
Jacob Bramley85a9c102019-12-09 17:48:29 +00004525bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4526 // To simulate fault-tolerant loads, we need to know what host addresses we
4527 // can access without generating a real fault. One way to do that is to
4528 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
4529 // and less intrusive than using (global) signal handlers.
4530 //
4531 // [1]: https://stackoverflow.com/questions/7134590
4532
4533 size_t written = 0;
4534 bool can_read = true;
4535 // `write` will normally return after one invocation, but it is allowed to
4536 // handle only part of the operation, so wrap it in a loop.
4537 while (can_read && (written < size)) {
4538 ssize_t result = write(dummy_pipe_fd_[1],
4539 reinterpret_cast<void*>(address + written),
4540 size - written);
4541 if (result > 0) {
4542 written += result;
4543 } else {
4544 switch (result) {
4545 case -EPERM:
4546 case -EFAULT:
4547 // The address range is not accessible.
4548 // `write` is supposed to return -EFAULT in this case, but in practice
4549 // it seems to return -EPERM, so we accept that too.
4550 can_read = false;
4551 break;
4552 case -EINTR:
4553 // The call was interrupted by a signal. Just try again.
4554 break;
4555 default:
4556 // Any other error is fatal.
4557 VIXL_ABORT();
4558 }
4559 }
4560 }
4561 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4562 // the dummy data is buffered. As before, we expect to drain the whole write
4563 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
4564 // function is primarily intended to implement SVE fault-tolerant loads, so
4565 // the maximum Z register size is a good default buffer size.
4566 char buffer[kZRegMaxSizeInBytes];
4567 while (written > 0) {
4568 ssize_t result = read(dummy_pipe_fd_[0],
4569 reinterpret_cast<void*>(buffer),
4570 sizeof(buffer));
4571 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4572 // we've read everything that was written, so treat 0 as an error.
4573 if (result > 0) {
4574 VIXL_ASSERT(static_cast<size_t>(result) <= written);
4575 written -= result;
4576 } else {
4577 // For -EINTR, just try again. We can't handle any other error.
4578 VIXL_CHECK(result == -EINTR);
4579 }
4580 }
4581
4582 return can_read;
4583}
Alexandre Ramesd3832962016-07-04 15:03:43 +01004584
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004585void Simulator::PrintExclusiveAccessWarning() {
4586 if (print_exclusive_access_warning_) {
4587 fprintf(stderr,
4588 "%sWARNING:%s VIXL simulator support for "
4589 "load-/store-/clear-exclusive "
4590 "instructions is limited. Refer to the README for details.%s\n",
4591 clr_warning,
4592 clr_warning_message,
4593 clr_normal);
4594 print_exclusive_access_warning_ = false;
4595 }
4596}
4597
Alexandre Ramesd3832962016-07-04 15:03:43 +01004598void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004599 LoadStoreExclusive op =
4600 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4601
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004602 switch (op) {
4603 case CAS_w:
4604 case CASA_w:
4605 case CASL_w:
4606 case CASAL_w:
4607 CompareAndSwapHelper<uint32_t>(instr);
4608 break;
4609 case CAS_x:
4610 case CASA_x:
4611 case CASL_x:
4612 case CASAL_x:
4613 CompareAndSwapHelper<uint64_t>(instr);
4614 break;
4615 case CASB:
4616 case CASAB:
4617 case CASLB:
4618 case CASALB:
4619 CompareAndSwapHelper<uint8_t>(instr);
4620 break;
4621 case CASH:
4622 case CASAH:
4623 case CASLH:
4624 case CASALH:
4625 CompareAndSwapHelper<uint16_t>(instr);
4626 break;
4627 case CASP_w:
4628 case CASPA_w:
4629 case CASPL_w:
4630 case CASPAL_w:
4631 CompareAndSwapPairHelper<uint32_t>(instr);
4632 break;
4633 case CASP_x:
4634 case CASPA_x:
4635 case CASPL_x:
4636 case CASPAL_x:
4637 CompareAndSwapPairHelper<uint64_t>(instr);
4638 break;
4639 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004640 PrintExclusiveAccessWarning();
4641
4642 unsigned rs = instr->GetRs();
4643 unsigned rt = instr->GetRt();
4644 unsigned rt2 = instr->GetRt2();
4645 unsigned rn = instr->GetRn();
4646
4647 bool is_exclusive = !instr->GetLdStXNotExclusive();
4648 bool is_acquire_release =
4649 !is_exclusive || instr->GetLdStXAcquireRelease();
4650 bool is_load = instr->GetLdStXLoad();
4651 bool is_pair = instr->GetLdStXPair();
4652
4653 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4654 unsigned access_size = is_pair ? element_size * 2 : element_size;
4655 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4656
4657 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4658
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004659 if (is_load) {
4660 if (is_exclusive) {
4661 local_monitor_.MarkExclusive(address, access_size);
4662 } else {
4663 // Any non-exclusive load can clear the local monitor as a side
4664 // effect. We don't need to do this, but it is useful to stress the
4665 // simulated code.
4666 local_monitor_.Clear();
4667 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004668
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004669 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4670 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00004671 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004672 switch (op) {
4673 case LDXRB_w:
4674 case LDAXRB_w:
4675 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004676 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004677 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004678 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004679 break;
4680 case LDXRH_w:
4681 case LDAXRH_w:
4682 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004683 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004684 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004685 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004686 break;
4687 case LDXR_w:
4688 case LDAXR_w:
4689 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004690 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004691 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004692 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004693 break;
4694 case LDXR_x:
4695 case LDAXR_x:
4696 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004697 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004698 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004699 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004700 break;
4701 case LDXP_w:
4702 case LDAXP_w:
4703 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4704 WriteWRegister(rt2,
4705 Memory::Read<uint32_t>(address + element_size),
4706 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004707 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004708 break;
4709 case LDXP_x:
4710 case LDAXP_x:
4711 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4712 WriteXRegister(rt2,
4713 Memory::Read<uint64_t>(address + element_size),
4714 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004715 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004716 break;
4717 default:
4718 VIXL_UNREACHABLE();
4719 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004720
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004721 if (is_acquire_release) {
4722 // Approximate load-acquire by issuing a full barrier after the load.
4723 __sync_synchronize();
4724 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004725
Jacob Bramley423e5422019-11-13 19:15:55 +00004726 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4727 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004728 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004729 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004730 }
4731 } else {
4732 if (is_acquire_release) {
4733 // Approximate store-release by issuing a full barrier before the
4734 // store.
4735 __sync_synchronize();
4736 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004737
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004738 bool do_store = true;
4739 if (is_exclusive) {
4740 do_store = local_monitor_.IsExclusive(address, access_size) &&
4741 global_monitor_.IsExclusive(address, access_size);
4742 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004743
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004744 // - All exclusive stores explicitly clear the local monitor.
4745 local_monitor_.Clear();
4746 } else {
4747 // - Any other store can clear the local monitor as a side effect.
4748 local_monitor_.MaybeClear();
4749 }
4750
4751 if (do_store) {
4752 switch (op) {
4753 case STXRB_w:
4754 case STLXRB_w:
4755 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004756 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004757 Memory::Write<uint8_t>(address, ReadWRegister(rt));
4758 break;
4759 case STXRH_w:
4760 case STLXRH_w:
4761 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004762 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004763 Memory::Write<uint16_t>(address, ReadWRegister(rt));
4764 break;
4765 case STXR_w:
4766 case STLXR_w:
4767 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004768 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004769 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4770 break;
4771 case STXR_x:
4772 case STLXR_x:
4773 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004774 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004775 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4776 break;
4777 case STXP_w:
4778 case STLXP_w:
4779 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4780 Memory::Write<uint32_t>(address + element_size,
4781 ReadWRegister(rt2));
4782 break;
4783 case STXP_x:
4784 case STLXP_x:
4785 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4786 Memory::Write<uint64_t>(address + element_size,
4787 ReadXRegister(rt2));
4788 break;
4789 default:
4790 VIXL_UNREACHABLE();
4791 }
4792
Jacob Bramley423e5422019-11-13 19:15:55 +00004793 PrintRegisterFormat format =
4794 GetPrintRegisterFormatForSize(element_size);
4795 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004796 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004797 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004798 }
4799 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004800 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004801 }
4802}
4803
Jacob Bramleyca789742018-09-13 14:25:46 +01004804template <typename T>
4805void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4806 unsigned rs = instr->GetRs();
4807 unsigned rt = instr->GetRt();
4808 unsigned rn = instr->GetRn();
4809
4810 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4811 bool is_release = instr->ExtractBit(22) == 1;
4812
4813 unsigned element_size = sizeof(T);
4814 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4815
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004816 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004817
4818 T value = ReadRegister<T>(rs);
4819
4820 T data = Memory::Read<T>(address);
4821
4822 if (is_acquire) {
4823 // Approximate load-acquire by issuing a full barrier after the load.
4824 __sync_synchronize();
4825 }
4826
4827 T result = 0;
4828 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4829 case LDADDOp:
4830 result = data + value;
4831 break;
4832 case LDCLROp:
4833 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4834 result = data & ~value;
4835 break;
4836 case LDEOROp:
4837 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4838 result = data ^ value;
4839 break;
4840 case LDSETOp:
4841 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4842 result = data | value;
4843 break;
4844
4845 // Signed/Unsigned difference is done via the templated type T.
4846 case LDSMAXOp:
4847 case LDUMAXOp:
4848 result = (data > value) ? data : value;
4849 break;
4850 case LDSMINOp:
4851 case LDUMINOp:
4852 result = (data > value) ? value : data;
4853 break;
4854 }
4855
4856 if (is_release) {
4857 // Approximate store-release by issuing a full barrier before the store.
4858 __sync_synchronize();
4859 }
4860
4861 Memory::Write<T>(address, result);
4862 WriteRegister<T>(rt, data, NoRegLog);
4863
Jacob Bramley423e5422019-11-13 19:15:55 +00004864 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4865 LogRead(rt, format, address);
4866 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004867}
4868
4869template <typename T>
4870void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4871 unsigned rs = instr->GetRs();
4872 unsigned rt = instr->GetRt();
4873 unsigned rn = instr->GetRn();
4874
4875 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4876 bool is_release = instr->ExtractBit(22) == 1;
4877
4878 unsigned element_size = sizeof(T);
4879 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4880
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004881 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004882
4883 T data = Memory::Read<T>(address);
4884 if (is_acquire) {
4885 // Approximate load-acquire by issuing a full barrier after the load.
4886 __sync_synchronize();
4887 }
4888
4889 if (is_release) {
4890 // Approximate store-release by issuing a full barrier before the store.
4891 __sync_synchronize();
4892 }
4893 Memory::Write<T>(address, ReadRegister<T>(rs));
4894
4895 WriteRegister<T>(rt, data);
4896
Jacob Bramley423e5422019-11-13 19:15:55 +00004897 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4898 LogRead(rt, format, address);
4899 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004900}
4901
4902template <typename T>
4903void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4904 unsigned rt = instr->GetRt();
4905 unsigned rn = instr->GetRn();
4906
4907 unsigned element_size = sizeof(T);
4908 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4909
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004910 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4911
Jacob Bramleyca789742018-09-13 14:25:46 +01004912 WriteRegister<T>(rt, Memory::Read<T>(address));
4913
4914 // Approximate load-acquire by issuing a full barrier after the load.
4915 __sync_synchronize();
4916
Jacob Bramley423e5422019-11-13 19:15:55 +00004917 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004918}
4919
4920#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4921 V(LDADD) \
4922 V(LDCLR) \
4923 V(LDEOR) \
4924 V(LDSET) \
4925 V(LDUMAX) \
4926 V(LDUMIN)
4927
4928#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4929 V(LDSMAX) \
4930 V(LDSMIN)
4931
4932void Simulator::VisitAtomicMemory(const Instruction* instr) {
4933 switch (instr->Mask(AtomicMemoryMask)) {
4934// clang-format off
4935#define SIM_FUNC_B(A) \
4936 case A##B: \
4937 case A##AB: \
4938 case A##LB: \
4939 case A##ALB:
4940#define SIM_FUNC_H(A) \
4941 case A##H: \
4942 case A##AH: \
4943 case A##LH: \
4944 case A##ALH:
4945#define SIM_FUNC_w(A) \
4946 case A##_w: \
4947 case A##A_w: \
4948 case A##L_w: \
4949 case A##AL_w:
4950#define SIM_FUNC_x(A) \
4951 case A##_x: \
4952 case A##A_x: \
4953 case A##L_x: \
4954 case A##AL_x:
4955
4956 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4957 AtomicMemorySimpleHelper<uint8_t>(instr);
4958 break;
4959 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4960 AtomicMemorySimpleHelper<int8_t>(instr);
4961 break;
4962 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4963 AtomicMemorySimpleHelper<uint16_t>(instr);
4964 break;
4965 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4966 AtomicMemorySimpleHelper<int16_t>(instr);
4967 break;
4968 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4969 AtomicMemorySimpleHelper<uint32_t>(instr);
4970 break;
4971 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4972 AtomicMemorySimpleHelper<int32_t>(instr);
4973 break;
4974 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4975 AtomicMemorySimpleHelper<uint64_t>(instr);
4976 break;
4977 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4978 AtomicMemorySimpleHelper<int64_t>(instr);
4979 break;
4980 // clang-format on
4981
4982 case SWPB:
4983 case SWPAB:
4984 case SWPLB:
4985 case SWPALB:
4986 AtomicMemorySwapHelper<uint8_t>(instr);
4987 break;
4988 case SWPH:
4989 case SWPAH:
4990 case SWPLH:
4991 case SWPALH:
4992 AtomicMemorySwapHelper<uint16_t>(instr);
4993 break;
4994 case SWP_w:
4995 case SWPA_w:
4996 case SWPL_w:
4997 case SWPAL_w:
4998 AtomicMemorySwapHelper<uint32_t>(instr);
4999 break;
5000 case SWP_x:
5001 case SWPA_x:
5002 case SWPL_x:
5003 case SWPAL_x:
5004 AtomicMemorySwapHelper<uint64_t>(instr);
5005 break;
5006 case LDAPRB:
5007 LoadAcquireRCpcHelper<uint8_t>(instr);
5008 break;
5009 case LDAPRH:
5010 LoadAcquireRCpcHelper<uint16_t>(instr);
5011 break;
5012 case LDAPR_w:
5013 LoadAcquireRCpcHelper<uint32_t>(instr);
5014 break;
5015 case LDAPR_x:
5016 LoadAcquireRCpcHelper<uint64_t>(instr);
5017 break;
5018 }
5019}
5020
Alexandre Ramesd3832962016-07-04 15:03:43 +01005021
5022void Simulator::VisitLoadLiteral(const Instruction* instr) {
5023 unsigned rt = instr->GetRt();
5024 uint64_t address = instr->GetLiteralAddress<uint64_t>();
5025
5026 // Verify that the calculated address is available to the host.
5027 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5028
5029 switch (instr->Mask(LoadLiteralMask)) {
5030 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
5031 // print a more detailed log.
5032 case LDR_w_lit:
5033 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005034 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005035 break;
5036 case LDR_x_lit:
5037 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005038 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005039 break;
5040 case LDR_s_lit:
5041 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005042 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005043 break;
5044 case LDR_d_lit:
5045 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005046 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005047 break;
5048 case LDR_q_lit:
5049 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005050 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005051 break;
5052 case LDRSW_x_lit:
5053 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005054 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005055 break;
5056
5057 // Ignore prfm hint instructions.
5058 case PRFM_lit:
5059 break;
5060
5061 default:
5062 VIXL_UNREACHABLE();
5063 }
5064
5065 local_monitor_.MaybeClear();
5066}
5067
5068
5069uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
5070 int64_t offset,
5071 AddrMode addrmode) {
5072 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
5073
5074 if ((addr_reg == 31) && ((address % 16) != 0)) {
5075 // When the base register is SP the stack pointer is required to be
5076 // quadword aligned prior to the address calculation and write-backs.
5077 // Misalignment will cause a stack alignment fault.
5078 VIXL_ALIGNMENT_EXCEPTION();
5079 }
5080
5081 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
5082 VIXL_ASSERT(offset != 0);
5083 // Only preindex should log the register update here. For Postindex, the
5084 // update will be printed automatically by LogWrittenRegisters _after_ the
5085 // memory access itself is logged.
5086 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5087 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5088 }
5089
5090 if ((addrmode == Offset) || (addrmode == PreIndex)) {
5091 address += offset;
5092 }
5093
5094 // Verify that the calculated address is available to the host.
5095 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5096
5097 return static_cast<uintptr_t>(address);
5098}
5099
5100
5101void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5102 MoveWideImmediateOp mov_op =
5103 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5104 int64_t new_xn_val = 0;
5105
5106 bool is_64_bits = instr->GetSixtyFourBits() == 1;
5107 // Shift is limited for W operations.
5108 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5109
5110 // Get the shifted immediate.
5111 int64_t shift = instr->GetShiftMoveWide() * 16;
5112 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5113 << shift;
5114
5115 // Compute the new value.
5116 switch (mov_op) {
5117 case MOVN_w:
5118 case MOVN_x: {
5119 new_xn_val = ~shifted_imm16;
5120 if (!is_64_bits) new_xn_val &= kWRegMask;
5121 break;
5122 }
5123 case MOVK_w:
5124 case MOVK_x: {
5125 unsigned reg_code = instr->GetRd();
5126 int64_t prev_xn_val =
5127 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5128 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5129 break;
5130 }
5131 case MOVZ_w:
5132 case MOVZ_x: {
5133 new_xn_val = shifted_imm16;
5134 break;
5135 }
5136 default:
5137 VIXL_UNREACHABLE();
5138 }
5139
5140 // Update the destination register.
5141 WriteXRegister(instr->GetRd(), new_xn_val);
5142}
5143
5144
5145void Simulator::VisitConditionalSelect(const Instruction* instr) {
5146 uint64_t new_val = ReadXRegister(instr->GetRn());
5147
5148 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5149 new_val = ReadXRegister(instr->GetRm());
5150 switch (instr->Mask(ConditionalSelectMask)) {
5151 case CSEL_w:
5152 case CSEL_x:
5153 break;
5154 case CSINC_w:
5155 case CSINC_x:
5156 new_val++;
5157 break;
5158 case CSINV_w:
5159 case CSINV_x:
5160 new_val = ~new_val;
5161 break;
5162 case CSNEG_w:
5163 case CSNEG_x:
5164 new_val = -new_val;
5165 break;
5166 default:
5167 VIXL_UNIMPLEMENTED();
5168 }
5169 }
5170 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5171 WriteRegister(reg_size, instr->GetRd(), new_val);
5172}
5173
5174
Jacob Bramleyca789742018-09-13 14:25:46 +01005175// clang-format off
5176#define PAUTH_MODES(V) \
5177 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
5178 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
5179 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
5180 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
5181 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
5182 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
5183 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
5184 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
5185// clang-format on
5186
Alexandre Ramesd3832962016-07-04 15:03:43 +01005187void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5188 unsigned dst = instr->GetRd();
5189 unsigned src = instr->GetRn();
5190
5191 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005192#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
5193 case PAC##SUFFIX: { \
5194 uint64_t ptr = ReadXRegister(dst); \
5195 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
5196 break; \
5197 } \
5198 case AUT##SUFFIX: { \
5199 uint64_t ptr = ReadXRegister(dst); \
5200 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
5201 break; \
5202 }
5203
5204 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
5205#undef DEFINE_PAUTH_FUNCS
5206
5207 case XPACI:
5208 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5209 break;
5210 case XPACD:
5211 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5212 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005213 case RBIT_w:
5214 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5215 break;
5216 case RBIT_x:
5217 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5218 break;
5219 case REV16_w:
5220 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5221 break;
5222 case REV16_x:
5223 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5224 break;
5225 case REV_w:
5226 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5227 break;
5228 case REV32_x:
5229 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5230 break;
5231 case REV_x:
5232 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5233 break;
5234 case CLZ_w:
5235 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5236 break;
5237 case CLZ_x:
5238 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5239 break;
5240 case CLS_w:
5241 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5242 break;
5243 case CLS_x:
5244 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5245 break;
5246 default:
5247 VIXL_UNIMPLEMENTED();
5248 }
5249}
5250
5251
5252uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5253 VIXL_ASSERT((n > 32) && (n <= 64));
5254 for (unsigned i = (n - 1); i >= 32; i--) {
5255 if (((data >> i) & 1) != 0) {
5256 uint64_t polysh32 = (uint64_t)poly << (i - 32);
5257 uint64_t mask = (UINT64_C(1) << i) - 1;
5258 data = ((data & mask) ^ polysh32);
5259 }
5260 }
5261 return data & 0xffffffff;
5262}
5263
5264
5265template <typename T>
5266uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5267 unsigned size = sizeof(val) * 8; // Number of bits in type T.
5268 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5269 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5270 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5271 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5272}
5273
5274
5275uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5276 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5277 // the CRC of each 32-bit word sequentially.
5278 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5279 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5280}
5281
5282
5283void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5284 Shift shift_op = NO_SHIFT;
5285 int64_t result = 0;
5286 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5287
5288 switch (instr->Mask(DataProcessing2SourceMask)) {
5289 case SDIV_w: {
5290 int32_t rn = ReadWRegister(instr->GetRn());
5291 int32_t rm = ReadWRegister(instr->GetRm());
5292 if ((rn == kWMinInt) && (rm == -1)) {
5293 result = kWMinInt;
5294 } else if (rm == 0) {
5295 // Division by zero can be trapped, but not on A-class processors.
5296 result = 0;
5297 } else {
5298 result = rn / rm;
5299 }
5300 break;
5301 }
5302 case SDIV_x: {
5303 int64_t rn = ReadXRegister(instr->GetRn());
5304 int64_t rm = ReadXRegister(instr->GetRm());
5305 if ((rn == kXMinInt) && (rm == -1)) {
5306 result = kXMinInt;
5307 } else if (rm == 0) {
5308 // Division by zero can be trapped, but not on A-class processors.
5309 result = 0;
5310 } else {
5311 result = rn / rm;
5312 }
5313 break;
5314 }
5315 case UDIV_w: {
5316 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5317 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5318 if (rm == 0) {
5319 // Division by zero can be trapped, but not on A-class processors.
5320 result = 0;
5321 } else {
5322 result = rn / rm;
5323 }
5324 break;
5325 }
5326 case UDIV_x: {
5327 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5328 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5329 if (rm == 0) {
5330 // Division by zero can be trapped, but not on A-class processors.
5331 result = 0;
5332 } else {
5333 result = rn / rm;
5334 }
5335 break;
5336 }
5337 case LSLV_w:
5338 case LSLV_x:
5339 shift_op = LSL;
5340 break;
5341 case LSRV_w:
5342 case LSRV_x:
5343 shift_op = LSR;
5344 break;
5345 case ASRV_w:
5346 case ASRV_x:
5347 shift_op = ASR;
5348 break;
5349 case RORV_w:
5350 case RORV_x:
5351 shift_op = ROR;
5352 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005353 case PACGA: {
5354 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5355 uint64_t src = static_cast<uint64_t>(
5356 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5357 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5358 result = code & 0xffffffff00000000;
5359 break;
5360 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005361 case CRC32B: {
5362 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5363 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5364 result = Crc32Checksum(acc, val, CRC32_POLY);
5365 break;
5366 }
5367 case CRC32H: {
5368 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5369 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5370 result = Crc32Checksum(acc, val, CRC32_POLY);
5371 break;
5372 }
5373 case CRC32W: {
5374 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5375 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5376 result = Crc32Checksum(acc, val, CRC32_POLY);
5377 break;
5378 }
5379 case CRC32X: {
5380 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5381 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5382 result = Crc32Checksum(acc, val, CRC32_POLY);
5383 reg_size = kWRegSize;
5384 break;
5385 }
5386 case CRC32CB: {
5387 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5388 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5389 result = Crc32Checksum(acc, val, CRC32C_POLY);
5390 break;
5391 }
5392 case CRC32CH: {
5393 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5394 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5395 result = Crc32Checksum(acc, val, CRC32C_POLY);
5396 break;
5397 }
5398 case CRC32CW: {
5399 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5400 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5401 result = Crc32Checksum(acc, val, CRC32C_POLY);
5402 break;
5403 }
5404 case CRC32CX: {
5405 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5406 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5407 result = Crc32Checksum(acc, val, CRC32C_POLY);
5408 reg_size = kWRegSize;
5409 break;
5410 }
5411 default:
5412 VIXL_UNIMPLEMENTED();
5413 }
5414
5415 if (shift_op != NO_SHIFT) {
5416 // Shift distance encoded in the least-significant five/six bits of the
5417 // register.
5418 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5419 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5420 result = ShiftOperand(reg_size,
5421 ReadRegister(reg_size, instr->GetRn()),
5422 shift_op,
5423 shift);
5424 }
5425 WriteRegister(reg_size, instr->GetRd(), result);
5426}
5427
5428
Alexandre Ramesd3832962016-07-04 15:03:43 +01005429void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5430 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5431
5432 uint64_t result = 0;
5433 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5434 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5435 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5436 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5437 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005438 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5439 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005440 switch (instr->Mask(DataProcessing3SourceMask)) {
5441 case MADD_w:
5442 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005443 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005444 break;
5445 case MSUB_w:
5446 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005447 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005448 break;
5449 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005450 result = ReadXRegister(instr->GetRa()) +
5451 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005452 break;
5453 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005454 result = ReadXRegister(instr->GetRa()) -
5455 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005456 break;
5457 case UMADDL_x:
5458 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5459 break;
5460 case UMSUBL_x:
5461 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5462 break;
5463 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005464 result =
5465 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5466 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005467 break;
5468 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005469 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5470 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005471 break;
5472 default:
5473 VIXL_UNIMPLEMENTED();
5474 }
5475 WriteRegister(reg_size, instr->GetRd(), result);
5476}
5477
5478
5479void Simulator::VisitBitfield(const Instruction* instr) {
5480 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5481 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005482 int R = instr->GetImmR();
5483 int S = instr->GetImmS();
5484 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005485 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005486 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005487 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005488 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005489 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005490 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005491 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005492 diff += reg_size;
5493 }
5494
5495 // inzero indicates if the extracted bitfield is inserted into the
5496 // destination register value or in zero.
5497 // If extend is true, extend the sign of the extracted bitfield.
5498 bool inzero = false;
5499 bool extend = false;
5500 switch (instr->Mask(BitfieldMask)) {
5501 case BFM_x:
5502 case BFM_w:
5503 break;
5504 case SBFM_x:
5505 case SBFM_w:
5506 inzero = true;
5507 extend = true;
5508 break;
5509 case UBFM_x:
5510 case UBFM_w:
5511 inzero = true;
5512 break;
5513 default:
5514 VIXL_UNIMPLEMENTED();
5515 }
5516
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005517 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5518 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005519 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005520 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005521 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005522 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5523 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005524
5525 // Merge sign extension, dest/zero and bitfield.
5526 result = signbits | (result & mask) | (dst & ~mask);
5527
5528 WriteRegister(reg_size, instr->GetRd(), result);
5529}
5530
5531
5532void Simulator::VisitExtract(const Instruction* instr) {
5533 unsigned lsb = instr->GetImmS();
5534 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5535 uint64_t low_res =
5536 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00005537 uint64_t high_res = (lsb == 0)
5538 ? 0
5539 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5540 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005541 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5542}
5543
5544
5545void Simulator::VisitFPImmediate(const Instruction* instr) {
5546 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005547 unsigned dest = instr->GetRd();
5548 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005549 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01005550 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01005551 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005552 case FMOV_s_imm:
5553 WriteSRegister(dest, instr->GetImmFP32());
5554 break;
5555 case FMOV_d_imm:
5556 WriteDRegister(dest, instr->GetImmFP64());
5557 break;
5558 default:
5559 VIXL_UNREACHABLE();
5560 }
5561}
5562
5563
5564void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5565 AssertSupportedFPCR();
5566
5567 unsigned dst = instr->GetRd();
5568 unsigned src = instr->GetRn();
5569
5570 FPRounding round = ReadRMode();
5571
5572 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005573 case FCVTAS_wh:
5574 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5575 break;
5576 case FCVTAS_xh:
5577 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5578 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005579 case FCVTAS_ws:
5580 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5581 break;
5582 case FCVTAS_xs:
5583 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5584 break;
5585 case FCVTAS_wd:
5586 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5587 break;
5588 case FCVTAS_xd:
5589 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5590 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005591 case FCVTAU_wh:
5592 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5593 break;
5594 case FCVTAU_xh:
5595 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5596 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005597 case FCVTAU_ws:
5598 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5599 break;
5600 case FCVTAU_xs:
5601 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5602 break;
5603 case FCVTAU_wd:
5604 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5605 break;
5606 case FCVTAU_xd:
5607 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5608 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005609 case FCVTMS_wh:
5610 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5611 break;
5612 case FCVTMS_xh:
5613 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5614 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005615 case FCVTMS_ws:
5616 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5617 break;
5618 case FCVTMS_xs:
5619 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5620 break;
5621 case FCVTMS_wd:
5622 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5623 break;
5624 case FCVTMS_xd:
5625 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5626 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005627 case FCVTMU_wh:
5628 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5629 break;
5630 case FCVTMU_xh:
5631 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5632 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005633 case FCVTMU_ws:
5634 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5635 break;
5636 case FCVTMU_xs:
5637 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5638 break;
5639 case FCVTMU_wd:
5640 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5641 break;
5642 case FCVTMU_xd:
5643 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5644 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005645 case FCVTPS_wh:
5646 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5647 break;
5648 case FCVTPS_xh:
5649 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5650 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005651 case FCVTPS_ws:
5652 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5653 break;
5654 case FCVTPS_xs:
5655 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5656 break;
5657 case FCVTPS_wd:
5658 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5659 break;
5660 case FCVTPS_xd:
5661 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5662 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005663 case FCVTPU_wh:
5664 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5665 break;
5666 case FCVTPU_xh:
5667 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5668 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005669 case FCVTPU_ws:
5670 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5671 break;
5672 case FCVTPU_xs:
5673 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5674 break;
5675 case FCVTPU_wd:
5676 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5677 break;
5678 case FCVTPU_xd:
5679 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5680 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005681 case FCVTNS_wh:
5682 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5683 break;
5684 case FCVTNS_xh:
5685 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5686 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005687 case FCVTNS_ws:
5688 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5689 break;
5690 case FCVTNS_xs:
5691 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5692 break;
5693 case FCVTNS_wd:
5694 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5695 break;
5696 case FCVTNS_xd:
5697 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5698 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005699 case FCVTNU_wh:
5700 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5701 break;
5702 case FCVTNU_xh:
5703 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5704 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005705 case FCVTNU_ws:
5706 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5707 break;
5708 case FCVTNU_xs:
5709 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5710 break;
5711 case FCVTNU_wd:
5712 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5713 break;
5714 case FCVTNU_xd:
5715 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5716 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005717 case FCVTZS_wh:
5718 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5719 break;
5720 case FCVTZS_xh:
5721 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5722 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005723 case FCVTZS_ws:
5724 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5725 break;
5726 case FCVTZS_xs:
5727 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5728 break;
5729 case FCVTZS_wd:
5730 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5731 break;
5732 case FCVTZS_xd:
5733 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5734 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005735 case FCVTZU_wh:
5736 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5737 break;
5738 case FCVTZU_xh:
5739 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5740 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005741 case FCVTZU_ws:
5742 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5743 break;
5744 case FCVTZU_xs:
5745 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5746 break;
5747 case FCVTZU_wd:
5748 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5749 break;
5750 case FCVTZU_xd:
5751 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5752 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005753 case FJCVTZS:
5754 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5755 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005756 case FMOV_hw:
5757 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5758 break;
5759 case FMOV_wh:
5760 WriteWRegister(dst, ReadHRegisterBits(src));
5761 break;
5762 case FMOV_xh:
5763 WriteXRegister(dst, ReadHRegisterBits(src));
5764 break;
5765 case FMOV_hx:
5766 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5767 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005768 case FMOV_ws:
5769 WriteWRegister(dst, ReadSRegisterBits(src));
5770 break;
5771 case FMOV_xd:
5772 WriteXRegister(dst, ReadDRegisterBits(src));
5773 break;
5774 case FMOV_sw:
5775 WriteSRegisterBits(dst, ReadWRegister(src));
5776 break;
5777 case FMOV_dx:
5778 WriteDRegisterBits(dst, ReadXRegister(src));
5779 break;
5780 case FMOV_d1_x:
5781 LogicVRegister(ReadVRegister(dst))
5782 .SetUint(kFormatD, 1, ReadXRegister(src));
5783 break;
5784 case FMOV_x_d1:
5785 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5786 break;
5787
5788 // A 32-bit input can be handled in the same way as a 64-bit input, since
5789 // the sign- or zero-extension will not affect the conversion.
5790 case SCVTF_dx:
5791 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5792 break;
5793 case SCVTF_dw:
5794 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5795 break;
5796 case UCVTF_dx:
5797 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5798 break;
5799 case UCVTF_dw: {
5800 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005801 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005802 break;
5803 }
5804 case SCVTF_sx:
5805 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5806 break;
5807 case SCVTF_sw:
5808 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5809 break;
5810 case UCVTF_sx:
5811 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5812 break;
5813 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01005814 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5815 break;
5816 }
5817 case SCVTF_hx:
5818 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5819 break;
5820 case SCVTF_hw:
5821 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5822 break;
5823 case UCVTF_hx:
5824 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5825 break;
5826 case UCVTF_hw: {
5827 WriteHRegister(dst,
5828 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005829 break;
5830 }
5831
5832 default:
5833 VIXL_UNREACHABLE();
5834 }
5835}
5836
5837
5838void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5839 AssertSupportedFPCR();
5840
5841 unsigned dst = instr->GetRd();
5842 unsigned src = instr->GetRn();
5843 int fbits = 64 - instr->GetFPScale();
5844
5845 FPRounding round = ReadRMode();
5846
5847 switch (instr->Mask(FPFixedPointConvertMask)) {
5848 // A 32-bit input can be handled in the same way as a 64-bit input, since
5849 // the sign- or zero-extension will not affect the conversion.
5850 case SCVTF_dx_fixed:
5851 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5852 break;
5853 case SCVTF_dw_fixed:
5854 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5855 break;
5856 case UCVTF_dx_fixed:
5857 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5858 break;
5859 case UCVTF_dw_fixed: {
5860 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005861 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005862 break;
5863 }
5864 case SCVTF_sx_fixed:
5865 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5866 break;
5867 case SCVTF_sw_fixed:
5868 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5869 break;
5870 case UCVTF_sx_fixed:
5871 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5872 break;
5873 case UCVTF_sw_fixed: {
5874 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005875 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5876 break;
5877 }
5878 case SCVTF_hx_fixed:
5879 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5880 break;
5881 case SCVTF_hw_fixed:
5882 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5883 break;
5884 case UCVTF_hx_fixed:
5885 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5886 break;
5887 case UCVTF_hw_fixed: {
5888 WriteHRegister(dst,
5889 UFixedToFloat16(ReadRegister<uint32_t>(src),
5890 fbits,
5891 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005892 break;
5893 }
5894 case FCVTZS_xd_fixed:
5895 WriteXRegister(dst,
5896 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5897 FPZero));
5898 break;
5899 case FCVTZS_wd_fixed:
5900 WriteWRegister(dst,
5901 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5902 FPZero));
5903 break;
5904 case FCVTZU_xd_fixed:
5905 WriteXRegister(dst,
5906 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5907 FPZero));
5908 break;
5909 case FCVTZU_wd_fixed:
5910 WriteWRegister(dst,
5911 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5912 FPZero));
5913 break;
5914 case FCVTZS_xs_fixed:
5915 WriteXRegister(dst,
5916 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5917 FPZero));
5918 break;
5919 case FCVTZS_ws_fixed:
5920 WriteWRegister(dst,
5921 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5922 FPZero));
5923 break;
5924 case FCVTZU_xs_fixed:
5925 WriteXRegister(dst,
5926 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5927 FPZero));
5928 break;
5929 case FCVTZU_ws_fixed:
5930 WriteWRegister(dst,
5931 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5932 FPZero));
5933 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005934 case FCVTZS_xh_fixed: {
5935 double output =
5936 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5937 WriteXRegister(dst, FPToInt64(output, FPZero));
5938 break;
5939 }
5940 case FCVTZS_wh_fixed: {
5941 double output =
5942 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5943 WriteWRegister(dst, FPToInt32(output, FPZero));
5944 break;
5945 }
5946 case FCVTZU_xh_fixed: {
5947 double output =
5948 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5949 WriteXRegister(dst, FPToUInt64(output, FPZero));
5950 break;
5951 }
5952 case FCVTZU_wh_fixed: {
5953 double output =
5954 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5955 WriteWRegister(dst, FPToUInt32(output, FPZero));
5956 break;
5957 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005958 default:
5959 VIXL_UNREACHABLE();
5960 }
5961}
5962
5963
5964void Simulator::VisitFPCompare(const Instruction* instr) {
5965 AssertSupportedFPCR();
5966
5967 FPTrapFlags trap = DisableTrap;
5968 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005969 case FCMPE_h:
5970 trap = EnableTrap;
5971 VIXL_FALLTHROUGH();
5972 case FCMP_h:
5973 FPCompare(ReadHRegister(instr->GetRn()),
5974 ReadHRegister(instr->GetRm()),
5975 trap);
5976 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005977 case FCMPE_s:
5978 trap = EnableTrap;
5979 VIXL_FALLTHROUGH();
5980 case FCMP_s:
5981 FPCompare(ReadSRegister(instr->GetRn()),
5982 ReadSRegister(instr->GetRm()),
5983 trap);
5984 break;
5985 case FCMPE_d:
5986 trap = EnableTrap;
5987 VIXL_FALLTHROUGH();
5988 case FCMP_d:
5989 FPCompare(ReadDRegister(instr->GetRn()),
5990 ReadDRegister(instr->GetRm()),
5991 trap);
5992 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005993 case FCMPE_h_zero:
5994 trap = EnableTrap;
5995 VIXL_FALLTHROUGH();
5996 case FCMP_h_zero:
5997 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5998 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005999 case FCMPE_s_zero:
6000 trap = EnableTrap;
6001 VIXL_FALLTHROUGH();
6002 case FCMP_s_zero:
6003 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
6004 break;
6005 case FCMPE_d_zero:
6006 trap = EnableTrap;
6007 VIXL_FALLTHROUGH();
6008 case FCMP_d_zero:
6009 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
6010 break;
6011 default:
6012 VIXL_UNIMPLEMENTED();
6013 }
6014}
6015
6016
6017void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
6018 AssertSupportedFPCR();
6019
6020 FPTrapFlags trap = DisableTrap;
6021 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006022 case FCCMPE_h:
6023 trap = EnableTrap;
6024 VIXL_FALLTHROUGH();
6025 case FCCMP_h:
6026 if (ConditionPassed(instr->GetCondition())) {
6027 FPCompare(ReadHRegister(instr->GetRn()),
6028 ReadHRegister(instr->GetRm()),
6029 trap);
6030 } else {
6031 ReadNzcv().SetFlags(instr->GetNzcv());
6032 LogSystemRegister(NZCV);
6033 }
6034 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006035 case FCCMPE_s:
6036 trap = EnableTrap;
6037 VIXL_FALLTHROUGH();
6038 case FCCMP_s:
6039 if (ConditionPassed(instr->GetCondition())) {
6040 FPCompare(ReadSRegister(instr->GetRn()),
6041 ReadSRegister(instr->GetRm()),
6042 trap);
6043 } else {
6044 ReadNzcv().SetFlags(instr->GetNzcv());
6045 LogSystemRegister(NZCV);
6046 }
6047 break;
6048 case FCCMPE_d:
6049 trap = EnableTrap;
6050 VIXL_FALLTHROUGH();
6051 case FCCMP_d:
6052 if (ConditionPassed(instr->GetCondition())) {
6053 FPCompare(ReadDRegister(instr->GetRn()),
6054 ReadDRegister(instr->GetRm()),
6055 trap);
6056 } else {
6057 ReadNzcv().SetFlags(instr->GetNzcv());
6058 LogSystemRegister(NZCV);
6059 }
6060 break;
6061 default:
6062 VIXL_UNIMPLEMENTED();
6063 }
6064}
6065
6066
6067void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
6068 AssertSupportedFPCR();
6069
6070 Instr selected;
6071 if (ConditionPassed(instr->GetCondition())) {
6072 selected = instr->GetRn();
6073 } else {
6074 selected = instr->GetRm();
6075 }
6076
6077 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006078 case FCSEL_h:
6079 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
6080 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006081 case FCSEL_s:
6082 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
6083 break;
6084 case FCSEL_d:
6085 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6086 break;
6087 default:
6088 VIXL_UNIMPLEMENTED();
6089 }
6090}
6091
6092
6093void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6094 AssertSupportedFPCR();
6095
6096 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006097 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006098 switch (instr->Mask(FPTypeMask)) {
6099 default:
6100 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6101 case FP64:
6102 vform = kFormatD;
6103 break;
6104 case FP32:
6105 vform = kFormatS;
6106 break;
6107 case FP16:
6108 vform = kFormatH;
6109 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006110 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006111
Alexandre Ramesd3832962016-07-04 15:03:43 +01006112 SimVRegister& rd = ReadVRegister(instr->GetRd());
6113 SimVRegister& rn = ReadVRegister(instr->GetRn());
6114 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006115 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006116
6117 unsigned fd = instr->GetRd();
6118 unsigned fn = instr->GetRn();
6119
6120 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01006121 case FMOV_h:
6122 WriteHRegister(fd, ReadHRegister(fn));
6123 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006124 case FMOV_s:
6125 WriteSRegister(fd, ReadSRegister(fn));
6126 return;
6127 case FMOV_d:
6128 WriteDRegister(fd, ReadDRegister(fn));
6129 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006130 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006131 case FABS_s:
6132 case FABS_d:
6133 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6134 // Explicitly log the register update whilst we have type information.
6135 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6136 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006137 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006138 case FNEG_s:
6139 case FNEG_d:
6140 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6141 // Explicitly log the register update whilst we have type information.
6142 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6143 return;
6144 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01006145 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006146 return;
6147 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01006148 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006149 return;
6150 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01006151 WriteHRegister(fd,
6152 Float16ToRawbits(
6153 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006154 return;
6155 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01006156 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006157 return;
6158 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01006159 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006160 return;
6161 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01006162 WriteHRegister(fd,
6163 Float16ToRawbits(
6164 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006165 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006166 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006167 case FSQRT_s:
6168 case FSQRT_d:
6169 fsqrt(vform, rd, rn);
6170 // Explicitly log the register update whilst we have type information.
6171 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6172 return;
TatWai Chong04471812019-03-19 14:29:00 -07006173 case FRINT32X_s:
6174 case FRINT32X_d:
6175 inexact_exception = true;
6176 frint_mode = kFrintToInt32;
6177 break; // Use FPCR rounding mode.
6178 case FRINT64X_s:
6179 case FRINT64X_d:
6180 inexact_exception = true;
6181 frint_mode = kFrintToInt64;
6182 break; // Use FPCR rounding mode.
6183 case FRINT32Z_s:
6184 case FRINT32Z_d:
6185 inexact_exception = true;
6186 frint_mode = kFrintToInt32;
6187 fpcr_rounding = FPZero;
6188 break;
6189 case FRINT64Z_s:
6190 case FRINT64Z_d:
6191 inexact_exception = true;
6192 frint_mode = kFrintToInt64;
6193 fpcr_rounding = FPZero;
6194 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006195 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006196 case FRINTI_s:
6197 case FRINTI_d:
6198 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01006199 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006200 case FRINTX_s:
6201 case FRINTX_d:
6202 inexact_exception = true;
6203 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006204 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006205 case FRINTA_s:
6206 case FRINTA_d:
6207 fpcr_rounding = FPTieAway;
6208 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006209 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006210 case FRINTM_s:
6211 case FRINTM_d:
6212 fpcr_rounding = FPNegativeInfinity;
6213 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006214 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006215 case FRINTN_s:
6216 case FRINTN_d:
6217 fpcr_rounding = FPTieEven;
6218 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006219 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006220 case FRINTP_s:
6221 case FRINTP_d:
6222 fpcr_rounding = FPPositiveInfinity;
6223 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006224 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006225 case FRINTZ_s:
6226 case FRINTZ_d:
6227 fpcr_rounding = FPZero;
6228 break;
6229 default:
6230 VIXL_UNIMPLEMENTED();
6231 }
6232
6233 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006234 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006235 // Explicitly log the register update whilst we have type information.
6236 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6237}
6238
6239
6240void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6241 AssertSupportedFPCR();
6242
Carey Williamsd8bb3572018-04-10 11:58:07 +01006243 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006244 switch (instr->Mask(FPTypeMask)) {
6245 default:
6246 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6247 case FP64:
6248 vform = kFormatD;
6249 break;
6250 case FP32:
6251 vform = kFormatS;
6252 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006253 case FP16:
6254 vform = kFormatH;
6255 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006256 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006257 SimVRegister& rd = ReadVRegister(instr->GetRd());
6258 SimVRegister& rn = ReadVRegister(instr->GetRn());
6259 SimVRegister& rm = ReadVRegister(instr->GetRm());
6260
6261 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006262 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006263 case FADD_s:
6264 case FADD_d:
6265 fadd(vform, rd, rn, rm);
6266 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006267 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006268 case FSUB_s:
6269 case FSUB_d:
6270 fsub(vform, rd, rn, rm);
6271 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006272 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006273 case FMUL_s:
6274 case FMUL_d:
6275 fmul(vform, rd, rn, rm);
6276 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006277 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006278 case FNMUL_s:
6279 case FNMUL_d:
6280 fnmul(vform, rd, rn, rm);
6281 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006282 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006283 case FDIV_s:
6284 case FDIV_d:
6285 fdiv(vform, rd, rn, rm);
6286 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006287 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006288 case FMAX_s:
6289 case FMAX_d:
6290 fmax(vform, rd, rn, rm);
6291 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006292 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006293 case FMIN_s:
6294 case FMIN_d:
6295 fmin(vform, rd, rn, rm);
6296 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006297 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006298 case FMAXNM_s:
6299 case FMAXNM_d:
6300 fmaxnm(vform, rd, rn, rm);
6301 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006302 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006303 case FMINNM_s:
6304 case FMINNM_d:
6305 fminnm(vform, rd, rn, rm);
6306 break;
6307 default:
6308 VIXL_UNREACHABLE();
6309 }
6310 // Explicitly log the register update whilst we have type information.
6311 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6312}
6313
6314
6315void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6316 AssertSupportedFPCR();
6317
6318 unsigned fd = instr->GetRd();
6319 unsigned fn = instr->GetRn();
6320 unsigned fm = instr->GetRm();
6321 unsigned fa = instr->GetRa();
6322
6323 switch (instr->Mask(FPDataProcessing3SourceMask)) {
6324 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01006325 case FMADD_h:
6326 WriteHRegister(fd,
6327 FPMulAdd(ReadHRegister(fa),
6328 ReadHRegister(fn),
6329 ReadHRegister(fm)));
6330 break;
6331 case FMSUB_h:
6332 WriteHRegister(fd,
6333 FPMulAdd(ReadHRegister(fa),
6334 -ReadHRegister(fn),
6335 ReadHRegister(fm)));
6336 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006337 case FMADD_s:
6338 WriteSRegister(fd,
6339 FPMulAdd(ReadSRegister(fa),
6340 ReadSRegister(fn),
6341 ReadSRegister(fm)));
6342 break;
6343 case FMSUB_s:
6344 WriteSRegister(fd,
6345 FPMulAdd(ReadSRegister(fa),
6346 -ReadSRegister(fn),
6347 ReadSRegister(fm)));
6348 break;
6349 case FMADD_d:
6350 WriteDRegister(fd,
6351 FPMulAdd(ReadDRegister(fa),
6352 ReadDRegister(fn),
6353 ReadDRegister(fm)));
6354 break;
6355 case FMSUB_d:
6356 WriteDRegister(fd,
6357 FPMulAdd(ReadDRegister(fa),
6358 -ReadDRegister(fn),
6359 ReadDRegister(fm)));
6360 break;
6361 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01006362 case FNMADD_h:
6363 WriteHRegister(fd,
6364 FPMulAdd(-ReadHRegister(fa),
6365 -ReadHRegister(fn),
6366 ReadHRegister(fm)));
6367 break;
6368 case FNMSUB_h:
6369 WriteHRegister(fd,
6370 FPMulAdd(-ReadHRegister(fa),
6371 ReadHRegister(fn),
6372 ReadHRegister(fm)));
6373 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006374 case FNMADD_s:
6375 WriteSRegister(fd,
6376 FPMulAdd(-ReadSRegister(fa),
6377 -ReadSRegister(fn),
6378 ReadSRegister(fm)));
6379 break;
6380 case FNMSUB_s:
6381 WriteSRegister(fd,
6382 FPMulAdd(-ReadSRegister(fa),
6383 ReadSRegister(fn),
6384 ReadSRegister(fm)));
6385 break;
6386 case FNMADD_d:
6387 WriteDRegister(fd,
6388 FPMulAdd(-ReadDRegister(fa),
6389 -ReadDRegister(fn),
6390 ReadDRegister(fm)));
6391 break;
6392 case FNMSUB_d:
6393 WriteDRegister(fd,
6394 FPMulAdd(-ReadDRegister(fa),
6395 ReadDRegister(fn),
6396 ReadDRegister(fm)));
6397 break;
6398 default:
6399 VIXL_UNIMPLEMENTED();
6400 }
6401}
6402
6403
6404bool Simulator::FPProcessNaNs(const Instruction* instr) {
6405 unsigned fd = instr->GetRd();
6406 unsigned fn = instr->GetRn();
6407 unsigned fm = instr->GetRm();
6408 bool done = false;
6409
6410 if (instr->Mask(FP64) == FP64) {
6411 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006412 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006413 WriteDRegister(fd, result);
6414 done = true;
6415 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006416 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006417 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006418 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006419 WriteSRegister(fd, result);
6420 done = true;
6421 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006422 } else {
6423 VIXL_ASSERT(instr->Mask(FP16) == FP16);
6424 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006425 }
6426
6427 return done;
6428}
6429
6430
6431void Simulator::SysOp_W(int op, int64_t val) {
6432 switch (op) {
6433 case IVAU:
6434 case CVAC:
6435 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01006436 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08006437 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006438 case CIVAC: {
6439 // Perform a dummy memory access to ensure that we have read access
6440 // to the specified address.
6441 volatile uint8_t y = Memory::Read<uint8_t>(val);
6442 USE(y);
6443 // TODO: Implement "case ZVA:".
6444 break;
6445 }
6446 default:
6447 VIXL_UNIMPLEMENTED();
6448 }
6449}
6450
6451
Jacob Bramleyca789742018-09-13 14:25:46 +01006452// clang-format off
6453#define PAUTH_SYSTEM_MODES(V) \
6454 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
6455 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
6456 V(AZ, 30, 0x00000000, kPACKeyIA) \
6457 V(BZ, 30, 0x00000000, kPACKeyIB) \
6458 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6459 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6460// clang-format on
6461
6462
Alexandre Ramesd3832962016-07-04 15:03:43 +01006463void Simulator::VisitSystem(const Instruction* instr) {
6464 // Some system instructions hijack their Op and Cp fields to represent a
6465 // range of immediates instead of indicating a different instruction. This
6466 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01006467 if (instr->GetInstructionBits() == XPACLRI) {
6468 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00006469 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6470 switch (instr->Mask(SystemPStateMask)) {
6471 case CFINV:
6472 ReadNzcv().SetC(!ReadC());
6473 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00006474 case AXFLAG:
6475 ReadNzcv().SetN(0);
6476 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6477 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6478 ReadNzcv().SetV(0);
6479 break;
6480 case XAFLAG: {
6481 // Can't set the flags in place due to the logical dependencies.
6482 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6483 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6484 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6485 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6486 ReadNzcv().SetN(n);
6487 ReadNzcv().SetZ(z);
6488 ReadNzcv().SetC(c);
6489 ReadNzcv().SetV(v);
6490 break;
6491 }
Alexander Gilday2487f142018-11-05 13:07:27 +00006492 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006493 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006494 // Check BType allows PACI[AB]SP instructions.
6495 if (PcIsInGuardedPage()) {
6496 Instr i = instr->Mask(SystemPAuthMask);
6497 if ((i == PACIASP) || (i == PACIBSP)) {
6498 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006499 case BranchFromGuardedNotToIP:
6500 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6501 // assume here to be zero. This allows execution of PACI[AB]SP when
6502 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00006503 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006504 case BranchFromUnguardedOrToIP:
6505 case BranchAndLink:
6506 break;
6507 }
6508 }
6509 }
6510
Jacob Bramleyca789742018-09-13 14:25:46 +01006511 switch (instr->Mask(SystemPAuthMask)) {
6512#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
6513 case PACI##SUFFIX: \
6514 WriteXRegister(DST, \
6515 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6516 break; \
6517 case AUTI##SUFFIX: \
6518 WriteXRegister(DST, \
6519 AuthPAC(ReadXRegister(DST), \
6520 MOD, \
6521 KEY, \
6522 kInstructionPointer)); \
6523 break;
6524
6525 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6526#undef DEFINE_PAUTH_FUNCS
6527 }
6528 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6529 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006530 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6531 switch (instr->Mask(SystemExclusiveMonitorMask)) {
6532 case CLREX: {
6533 PrintExclusiveAccessWarning();
6534 ClearLocalMonitor();
6535 break;
6536 }
6537 }
6538 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6539 switch (instr->Mask(SystemSysRegMask)) {
6540 case MRS: {
6541 switch (instr->GetImmSystemRegister()) {
6542 case NZCV:
6543 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6544 break;
6545 case FPCR:
6546 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6547 break;
TatWai Chong04edf682018-12-27 16:01:02 -08006548 case RNDR:
6549 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00006550 uint64_t high = jrand48(rand_state_);
6551 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08006552 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6553 WriteXRegister(instr->GetRt(), rand_num);
6554 // Simulate successful random number generation.
6555 // TODO: Return failure occasionally as a random number cannot be
6556 // returned in a period of time.
6557 ReadNzcv().SetRawValue(NoFlag);
6558 LogSystemRegister(NZCV);
6559 break;
6560 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006561 default:
6562 VIXL_UNIMPLEMENTED();
6563 }
6564 break;
6565 }
6566 case MSR: {
6567 switch (instr->GetImmSystemRegister()) {
6568 case NZCV:
6569 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6570 LogSystemRegister(NZCV);
6571 break;
6572 case FPCR:
6573 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6574 LogSystemRegister(FPCR);
6575 break;
6576 default:
6577 VIXL_UNIMPLEMENTED();
6578 }
6579 break;
6580 }
6581 }
6582 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6583 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6584 switch (instr->GetImmHint()) {
6585 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01006586 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00006587 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006588 case BTI_jc:
6589 break;
6590 case BTI:
6591 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6592 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6593 }
6594 break;
6595 case BTI_c:
6596 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6597 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6598 }
6599 break;
6600 case BTI_j:
6601 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6602 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6603 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006604 break;
6605 default:
6606 VIXL_UNIMPLEMENTED();
6607 }
6608 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6609 __sync_synchronize();
6610 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6611 switch (instr->Mask(SystemSysMask)) {
6612 case SYS:
6613 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6614 break;
6615 default:
6616 VIXL_UNIMPLEMENTED();
6617 }
6618 } else {
6619 VIXL_UNIMPLEMENTED();
6620 }
6621}
6622
6623
6624void Simulator::VisitException(const Instruction* instr) {
6625 switch (instr->Mask(ExceptionMask)) {
6626 case HLT:
6627 switch (instr->GetImmException()) {
6628 case kUnreachableOpcode:
6629 DoUnreachable(instr);
6630 return;
6631 case kTraceOpcode:
6632 DoTrace(instr);
6633 return;
6634 case kLogOpcode:
6635 DoLog(instr);
6636 return;
6637 case kPrintfOpcode:
6638 DoPrintf(instr);
6639 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01006640 case kRuntimeCallOpcode:
6641 DoRuntimeCall(instr);
6642 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01006643 case kSetCPUFeaturesOpcode:
6644 case kEnableCPUFeaturesOpcode:
6645 case kDisableCPUFeaturesOpcode:
6646 DoConfigureCPUFeatures(instr);
6647 return;
6648 case kSaveCPUFeaturesOpcode:
6649 DoSaveCPUFeatures(instr);
6650 return;
6651 case kRestoreCPUFeaturesOpcode:
6652 DoRestoreCPUFeatures(instr);
6653 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006654 default:
6655 HostBreakpoint();
6656 return;
6657 }
6658 case BRK:
6659 HostBreakpoint();
6660 return;
6661 default:
6662 VIXL_UNIMPLEMENTED();
6663 }
6664}
6665
6666
6667void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6668 VisitUnimplemented(instr);
6669}
6670
6671
6672void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6673 VisitUnimplemented(instr);
6674}
6675
6676
6677void Simulator::VisitCryptoAES(const Instruction* instr) {
6678 VisitUnimplemented(instr);
6679}
6680
6681
6682void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6683 NEONFormatDecoder nfd(instr);
6684 VectorFormat vf = nfd.GetVectorFormat();
6685
6686 static const NEONFormatMap map_lp =
6687 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6688 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6689
6690 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6691 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6692
6693 static const NEONFormatMap map_fcvtn = {{22, 30},
6694 {NF_4H, NF_8H, NF_2S, NF_4S}};
6695 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6696
6697 SimVRegister& rd = ReadVRegister(instr->GetRd());
6698 SimVRegister& rn = ReadVRegister(instr->GetRn());
6699
6700 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6701 // These instructions all use a two bit size field, except NOT and RBIT,
6702 // which use the field to encode the operation.
6703 switch (instr->Mask(NEON2RegMiscMask)) {
6704 case NEON_REV64:
6705 rev64(vf, rd, rn);
6706 break;
6707 case NEON_REV32:
6708 rev32(vf, rd, rn);
6709 break;
6710 case NEON_REV16:
6711 rev16(vf, rd, rn);
6712 break;
6713 case NEON_SUQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006714 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006715 break;
6716 case NEON_USQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006717 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006718 break;
6719 case NEON_CLS:
6720 cls(vf, rd, rn);
6721 break;
6722 case NEON_CLZ:
6723 clz(vf, rd, rn);
6724 break;
6725 case NEON_CNT:
6726 cnt(vf, rd, rn);
6727 break;
6728 case NEON_SQABS:
6729 abs(vf, rd, rn).SignedSaturate(vf);
6730 break;
6731 case NEON_SQNEG:
6732 neg(vf, rd, rn).SignedSaturate(vf);
6733 break;
6734 case NEON_CMGT_zero:
6735 cmp(vf, rd, rn, 0, gt);
6736 break;
6737 case NEON_CMGE_zero:
6738 cmp(vf, rd, rn, 0, ge);
6739 break;
6740 case NEON_CMEQ_zero:
6741 cmp(vf, rd, rn, 0, eq);
6742 break;
6743 case NEON_CMLE_zero:
6744 cmp(vf, rd, rn, 0, le);
6745 break;
6746 case NEON_CMLT_zero:
6747 cmp(vf, rd, rn, 0, lt);
6748 break;
6749 case NEON_ABS:
6750 abs(vf, rd, rn);
6751 break;
6752 case NEON_NEG:
6753 neg(vf, rd, rn);
6754 break;
6755 case NEON_SADDLP:
6756 saddlp(vf_lp, rd, rn);
6757 break;
6758 case NEON_UADDLP:
6759 uaddlp(vf_lp, rd, rn);
6760 break;
6761 case NEON_SADALP:
6762 sadalp(vf_lp, rd, rn);
6763 break;
6764 case NEON_UADALP:
6765 uadalp(vf_lp, rd, rn);
6766 break;
6767 case NEON_RBIT_NOT:
6768 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6769 switch (instr->GetFPType()) {
6770 case 0:
6771 not_(vf, rd, rn);
6772 break;
6773 case 1:
6774 rbit(vf, rd, rn);
6775 break;
6776 default:
6777 VIXL_UNIMPLEMENTED();
6778 }
6779 break;
6780 }
6781 } else {
6782 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6783 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6784 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006785 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006786
6787 // These instructions all use a one bit size field, except XTN, SQXTUN,
6788 // SHLL, SQXTN and UQXTN, which use a two bit size field.
6789 switch (instr->Mask(NEON2RegMiscFPMask)) {
6790 case NEON_FABS:
6791 fabs_(fpf, rd, rn);
6792 return;
6793 case NEON_FNEG:
6794 fneg(fpf, rd, rn);
6795 return;
6796 case NEON_FSQRT:
6797 fsqrt(fpf, rd, rn);
6798 return;
6799 case NEON_FCVTL:
6800 if (instr->Mask(NEON_Q)) {
6801 fcvtl2(vf_fcvtl, rd, rn);
6802 } else {
6803 fcvtl(vf_fcvtl, rd, rn);
6804 }
6805 return;
6806 case NEON_FCVTN:
6807 if (instr->Mask(NEON_Q)) {
6808 fcvtn2(vf_fcvtn, rd, rn);
6809 } else {
6810 fcvtn(vf_fcvtn, rd, rn);
6811 }
6812 return;
6813 case NEON_FCVTXN:
6814 if (instr->Mask(NEON_Q)) {
6815 fcvtxn2(vf_fcvtn, rd, rn);
6816 } else {
6817 fcvtxn(vf_fcvtn, rd, rn);
6818 }
6819 return;
6820
6821 // The following instructions break from the switch statement, rather
6822 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07006823 case NEON_FRINT32X:
6824 inexact_exception = true;
6825 frint_mode = kFrintToInt32;
6826 break; // Use FPCR rounding mode.
6827 case NEON_FRINT32Z:
6828 inexact_exception = true;
6829 frint_mode = kFrintToInt32;
6830 fpcr_rounding = FPZero;
6831 break;
6832 case NEON_FRINT64X:
6833 inexact_exception = true;
6834 frint_mode = kFrintToInt64;
6835 break; // Use FPCR rounding mode.
6836 case NEON_FRINT64Z:
6837 inexact_exception = true;
6838 frint_mode = kFrintToInt64;
6839 fpcr_rounding = FPZero;
6840 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006841 case NEON_FRINTI:
6842 break; // Use FPCR rounding mode.
6843 case NEON_FRINTX:
6844 inexact_exception = true;
6845 break;
6846 case NEON_FRINTA:
6847 fpcr_rounding = FPTieAway;
6848 break;
6849 case NEON_FRINTM:
6850 fpcr_rounding = FPNegativeInfinity;
6851 break;
6852 case NEON_FRINTN:
6853 fpcr_rounding = FPTieEven;
6854 break;
6855 case NEON_FRINTP:
6856 fpcr_rounding = FPPositiveInfinity;
6857 break;
6858 case NEON_FRINTZ:
6859 fpcr_rounding = FPZero;
6860 break;
6861
6862 case NEON_FCVTNS:
6863 fcvts(fpf, rd, rn, FPTieEven);
6864 return;
6865 case NEON_FCVTNU:
6866 fcvtu(fpf, rd, rn, FPTieEven);
6867 return;
6868 case NEON_FCVTPS:
6869 fcvts(fpf, rd, rn, FPPositiveInfinity);
6870 return;
6871 case NEON_FCVTPU:
6872 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6873 return;
6874 case NEON_FCVTMS:
6875 fcvts(fpf, rd, rn, FPNegativeInfinity);
6876 return;
6877 case NEON_FCVTMU:
6878 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6879 return;
6880 case NEON_FCVTZS:
6881 fcvts(fpf, rd, rn, FPZero);
6882 return;
6883 case NEON_FCVTZU:
6884 fcvtu(fpf, rd, rn, FPZero);
6885 return;
6886 case NEON_FCVTAS:
6887 fcvts(fpf, rd, rn, FPTieAway);
6888 return;
6889 case NEON_FCVTAU:
6890 fcvtu(fpf, rd, rn, FPTieAway);
6891 return;
6892 case NEON_SCVTF:
6893 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6894 return;
6895 case NEON_UCVTF:
6896 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6897 return;
6898 case NEON_URSQRTE:
6899 ursqrte(fpf, rd, rn);
6900 return;
6901 case NEON_URECPE:
6902 urecpe(fpf, rd, rn);
6903 return;
6904 case NEON_FRSQRTE:
6905 frsqrte(fpf, rd, rn);
6906 return;
6907 case NEON_FRECPE:
6908 frecpe(fpf, rd, rn, fpcr_rounding);
6909 return;
6910 case NEON_FCMGT_zero:
6911 fcmp_zero(fpf, rd, rn, gt);
6912 return;
6913 case NEON_FCMGE_zero:
6914 fcmp_zero(fpf, rd, rn, ge);
6915 return;
6916 case NEON_FCMEQ_zero:
6917 fcmp_zero(fpf, rd, rn, eq);
6918 return;
6919 case NEON_FCMLE_zero:
6920 fcmp_zero(fpf, rd, rn, le);
6921 return;
6922 case NEON_FCMLT_zero:
6923 fcmp_zero(fpf, rd, rn, lt);
6924 return;
6925 default:
6926 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6927 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6928 switch (instr->Mask(NEON2RegMiscMask)) {
6929 case NEON_XTN:
6930 xtn(vf, rd, rn);
6931 return;
6932 case NEON_SQXTN:
6933 sqxtn(vf, rd, rn);
6934 return;
6935 case NEON_UQXTN:
6936 uqxtn(vf, rd, rn);
6937 return;
6938 case NEON_SQXTUN:
6939 sqxtun(vf, rd, rn);
6940 return;
6941 case NEON_SHLL:
6942 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6943 if (instr->Mask(NEON_Q)) {
6944 shll2(vf, rd, rn);
6945 } else {
6946 shll(vf, rd, rn);
6947 }
6948 return;
6949 default:
6950 VIXL_UNIMPLEMENTED();
6951 }
6952 } else {
6953 VIXL_UNIMPLEMENTED();
6954 }
6955 }
6956
6957 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006958 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006959 }
6960}
6961
6962
Jacob Bramleyca789742018-09-13 14:25:46 +01006963void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6964 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6965 NEONFormatDecoder nfd(instr);
6966 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6967
6968 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6969
6970 SimVRegister& rd = ReadVRegister(instr->GetRd());
6971 SimVRegister& rn = ReadVRegister(instr->GetRn());
6972
6973 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6974 case NEON_SCVTF_H:
6975 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6976 return;
6977 case NEON_UCVTF_H:
6978 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6979 return;
6980 case NEON_FCVTNS_H:
6981 fcvts(fpf, rd, rn, FPTieEven);
6982 return;
6983 case NEON_FCVTNU_H:
6984 fcvtu(fpf, rd, rn, FPTieEven);
6985 return;
6986 case NEON_FCVTPS_H:
6987 fcvts(fpf, rd, rn, FPPositiveInfinity);
6988 return;
6989 case NEON_FCVTPU_H:
6990 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6991 return;
6992 case NEON_FCVTMS_H:
6993 fcvts(fpf, rd, rn, FPNegativeInfinity);
6994 return;
6995 case NEON_FCVTMU_H:
6996 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6997 return;
6998 case NEON_FCVTZS_H:
6999 fcvts(fpf, rd, rn, FPZero);
7000 return;
7001 case NEON_FCVTZU_H:
7002 fcvtu(fpf, rd, rn, FPZero);
7003 return;
7004 case NEON_FCVTAS_H:
7005 fcvts(fpf, rd, rn, FPTieAway);
7006 return;
7007 case NEON_FCVTAU_H:
7008 fcvtu(fpf, rd, rn, FPTieAway);
7009 return;
7010 case NEON_FRINTI_H:
7011 frint(fpf, rd, rn, fpcr_rounding, false);
7012 return;
7013 case NEON_FRINTX_H:
7014 frint(fpf, rd, rn, fpcr_rounding, true);
7015 return;
7016 case NEON_FRINTA_H:
7017 frint(fpf, rd, rn, FPTieAway, false);
7018 return;
7019 case NEON_FRINTM_H:
7020 frint(fpf, rd, rn, FPNegativeInfinity, false);
7021 return;
7022 case NEON_FRINTN_H:
7023 frint(fpf, rd, rn, FPTieEven, false);
7024 return;
7025 case NEON_FRINTP_H:
7026 frint(fpf, rd, rn, FPPositiveInfinity, false);
7027 return;
7028 case NEON_FRINTZ_H:
7029 frint(fpf, rd, rn, FPZero, false);
7030 return;
7031 case NEON_FABS_H:
7032 fabs_(fpf, rd, rn);
7033 return;
7034 case NEON_FNEG_H:
7035 fneg(fpf, rd, rn);
7036 return;
7037 case NEON_FSQRT_H:
7038 fsqrt(fpf, rd, rn);
7039 return;
7040 case NEON_FRSQRTE_H:
7041 frsqrte(fpf, rd, rn);
7042 return;
7043 case NEON_FRECPE_H:
7044 frecpe(fpf, rd, rn, fpcr_rounding);
7045 return;
7046 case NEON_FCMGT_H_zero:
7047 fcmp_zero(fpf, rd, rn, gt);
7048 return;
7049 case NEON_FCMGE_H_zero:
7050 fcmp_zero(fpf, rd, rn, ge);
7051 return;
7052 case NEON_FCMEQ_H_zero:
7053 fcmp_zero(fpf, rd, rn, eq);
7054 return;
7055 case NEON_FCMLE_H_zero:
7056 fcmp_zero(fpf, rd, rn, le);
7057 return;
7058 case NEON_FCMLT_H_zero:
7059 fcmp_zero(fpf, rd, rn, lt);
7060 return;
7061 default:
7062 VIXL_UNIMPLEMENTED();
7063 return;
7064 }
7065}
7066
7067
Alexandre Ramesd3832962016-07-04 15:03:43 +01007068void Simulator::VisitNEON3Same(const Instruction* instr) {
7069 NEONFormatDecoder nfd(instr);
7070 SimVRegister& rd = ReadVRegister(instr->GetRd());
7071 SimVRegister& rn = ReadVRegister(instr->GetRn());
7072 SimVRegister& rm = ReadVRegister(instr->GetRm());
7073
7074 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
7075 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7076 switch (instr->Mask(NEON3SameLogicalMask)) {
7077 case NEON_AND:
7078 and_(vf, rd, rn, rm);
7079 break;
7080 case NEON_ORR:
7081 orr(vf, rd, rn, rm);
7082 break;
7083 case NEON_ORN:
7084 orn(vf, rd, rn, rm);
7085 break;
7086 case NEON_EOR:
7087 eor(vf, rd, rn, rm);
7088 break;
7089 case NEON_BIC:
7090 bic(vf, rd, rn, rm);
7091 break;
7092 case NEON_BIF:
7093 bif(vf, rd, rn, rm);
7094 break;
7095 case NEON_BIT:
7096 bit(vf, rd, rn, rm);
7097 break;
7098 case NEON_BSL:
Martyn Capewellb1b95782020-10-23 15:59:49 +01007099 bsl(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007100 break;
7101 default:
7102 VIXL_UNIMPLEMENTED();
7103 }
7104 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7105 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7106 switch (instr->Mask(NEON3SameFPMask)) {
7107 case NEON_FADD:
7108 fadd(vf, rd, rn, rm);
7109 break;
7110 case NEON_FSUB:
7111 fsub(vf, rd, rn, rm);
7112 break;
7113 case NEON_FMUL:
7114 fmul(vf, rd, rn, rm);
7115 break;
7116 case NEON_FDIV:
7117 fdiv(vf, rd, rn, rm);
7118 break;
7119 case NEON_FMAX:
7120 fmax(vf, rd, rn, rm);
7121 break;
7122 case NEON_FMIN:
7123 fmin(vf, rd, rn, rm);
7124 break;
7125 case NEON_FMAXNM:
7126 fmaxnm(vf, rd, rn, rm);
7127 break;
7128 case NEON_FMINNM:
7129 fminnm(vf, rd, rn, rm);
7130 break;
7131 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007132 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007133 break;
7134 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007135 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007136 break;
7137 case NEON_FMULX:
7138 fmulx(vf, rd, rn, rm);
7139 break;
7140 case NEON_FACGE:
7141 fabscmp(vf, rd, rn, rm, ge);
7142 break;
7143 case NEON_FACGT:
7144 fabscmp(vf, rd, rn, rm, gt);
7145 break;
7146 case NEON_FCMEQ:
7147 fcmp(vf, rd, rn, rm, eq);
7148 break;
7149 case NEON_FCMGE:
7150 fcmp(vf, rd, rn, rm, ge);
7151 break;
7152 case NEON_FCMGT:
7153 fcmp(vf, rd, rn, rm, gt);
7154 break;
7155 case NEON_FRECPS:
7156 frecps(vf, rd, rn, rm);
7157 break;
7158 case NEON_FRSQRTS:
7159 frsqrts(vf, rd, rn, rm);
7160 break;
7161 case NEON_FABD:
7162 fabd(vf, rd, rn, rm);
7163 break;
7164 case NEON_FADDP:
7165 faddp(vf, rd, rn, rm);
7166 break;
7167 case NEON_FMAXP:
7168 fmaxp(vf, rd, rn, rm);
7169 break;
7170 case NEON_FMAXNMP:
7171 fmaxnmp(vf, rd, rn, rm);
7172 break;
7173 case NEON_FMINP:
7174 fminp(vf, rd, rn, rm);
7175 break;
7176 case NEON_FMINNMP:
7177 fminnmp(vf, rd, rn, rm);
7178 break;
7179 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007180 // FMLAL{2} and FMLSL{2} have special-case encodings.
7181 switch (instr->Mask(NEON3SameFHMMask)) {
7182 case NEON_FMLAL:
7183 fmlal(vf, rd, rn, rm);
7184 break;
7185 case NEON_FMLAL2:
7186 fmlal2(vf, rd, rn, rm);
7187 break;
7188 case NEON_FMLSL:
7189 fmlsl(vf, rd, rn, rm);
7190 break;
7191 case NEON_FMLSL2:
7192 fmlsl2(vf, rd, rn, rm);
7193 break;
7194 default:
7195 VIXL_UNIMPLEMENTED();
7196 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007197 }
7198 } else {
7199 VectorFormat vf = nfd.GetVectorFormat();
7200 switch (instr->Mask(NEON3SameMask)) {
7201 case NEON_ADD:
7202 add(vf, rd, rn, rm);
7203 break;
7204 case NEON_ADDP:
7205 addp(vf, rd, rn, rm);
7206 break;
7207 case NEON_CMEQ:
7208 cmp(vf, rd, rn, rm, eq);
7209 break;
7210 case NEON_CMGE:
7211 cmp(vf, rd, rn, rm, ge);
7212 break;
7213 case NEON_CMGT:
7214 cmp(vf, rd, rn, rm, gt);
7215 break;
7216 case NEON_CMHI:
7217 cmp(vf, rd, rn, rm, hi);
7218 break;
7219 case NEON_CMHS:
7220 cmp(vf, rd, rn, rm, hs);
7221 break;
7222 case NEON_CMTST:
7223 cmptst(vf, rd, rn, rm);
7224 break;
7225 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01007226 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007227 break;
7228 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01007229 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007230 break;
7231 case NEON_MUL:
7232 mul(vf, rd, rn, rm);
7233 break;
7234 case NEON_PMUL:
7235 pmul(vf, rd, rn, rm);
7236 break;
7237 case NEON_SMAX:
7238 smax(vf, rd, rn, rm);
7239 break;
7240 case NEON_SMAXP:
7241 smaxp(vf, rd, rn, rm);
7242 break;
7243 case NEON_SMIN:
7244 smin(vf, rd, rn, rm);
7245 break;
7246 case NEON_SMINP:
7247 sminp(vf, rd, rn, rm);
7248 break;
7249 case NEON_SUB:
7250 sub(vf, rd, rn, rm);
7251 break;
7252 case NEON_UMAX:
7253 umax(vf, rd, rn, rm);
7254 break;
7255 case NEON_UMAXP:
7256 umaxp(vf, rd, rn, rm);
7257 break;
7258 case NEON_UMIN:
7259 umin(vf, rd, rn, rm);
7260 break;
7261 case NEON_UMINP:
7262 uminp(vf, rd, rn, rm);
7263 break;
7264 case NEON_SSHL:
7265 sshl(vf, rd, rn, rm);
7266 break;
7267 case NEON_USHL:
7268 ushl(vf, rd, rn, rm);
7269 break;
7270 case NEON_SABD:
7271 absdiff(vf, rd, rn, rm, true);
7272 break;
7273 case NEON_UABD:
7274 absdiff(vf, rd, rn, rm, false);
7275 break;
7276 case NEON_SABA:
7277 saba(vf, rd, rn, rm);
7278 break;
7279 case NEON_UABA:
7280 uaba(vf, rd, rn, rm);
7281 break;
7282 case NEON_UQADD:
7283 add(vf, rd, rn, rm).UnsignedSaturate(vf);
7284 break;
7285 case NEON_SQADD:
7286 add(vf, rd, rn, rm).SignedSaturate(vf);
7287 break;
7288 case NEON_UQSUB:
7289 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7290 break;
7291 case NEON_SQSUB:
7292 sub(vf, rd, rn, rm).SignedSaturate(vf);
7293 break;
7294 case NEON_SQDMULH:
7295 sqdmulh(vf, rd, rn, rm);
7296 break;
7297 case NEON_SQRDMULH:
7298 sqrdmulh(vf, rd, rn, rm);
7299 break;
7300 case NEON_UQSHL:
7301 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7302 break;
7303 case NEON_SQSHL:
7304 sshl(vf, rd, rn, rm).SignedSaturate(vf);
7305 break;
7306 case NEON_URSHL:
7307 ushl(vf, rd, rn, rm).Round(vf);
7308 break;
7309 case NEON_SRSHL:
7310 sshl(vf, rd, rn, rm).Round(vf);
7311 break;
7312 case NEON_UQRSHL:
7313 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7314 break;
7315 case NEON_SQRSHL:
7316 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7317 break;
7318 case NEON_UHADD:
7319 add(vf, rd, rn, rm).Uhalve(vf);
7320 break;
7321 case NEON_URHADD:
7322 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7323 break;
7324 case NEON_SHADD:
7325 add(vf, rd, rn, rm).Halve(vf);
7326 break;
7327 case NEON_SRHADD:
7328 add(vf, rd, rn, rm).Halve(vf).Round(vf);
7329 break;
7330 case NEON_UHSUB:
7331 sub(vf, rd, rn, rm).Uhalve(vf);
7332 break;
7333 case NEON_SHSUB:
7334 sub(vf, rd, rn, rm).Halve(vf);
7335 break;
7336 default:
7337 VIXL_UNIMPLEMENTED();
7338 }
7339 }
7340}
7341
7342
Jacob Bramleyca789742018-09-13 14:25:46 +01007343void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7344 NEONFormatDecoder nfd(instr);
7345 SimVRegister& rd = ReadVRegister(instr->GetRd());
7346 SimVRegister& rn = ReadVRegister(instr->GetRn());
7347 SimVRegister& rm = ReadVRegister(instr->GetRm());
7348
7349 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7350 switch (instr->Mask(NEON3SameFP16Mask)) {
7351#define SIM_FUNC(A, B) \
7352 case NEON_##A##_H: \
7353 B(vf, rd, rn, rm); \
7354 break;
7355 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007356 SIM_FUNC(FADD, fadd);
7357 SIM_FUNC(FMULX, fmulx);
7358 SIM_FUNC(FMAX, fmax);
7359 SIM_FUNC(FRECPS, frecps);
7360 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007361 SIM_FUNC(FSUB, fsub);
7362 SIM_FUNC(FMIN, fmin);
7363 SIM_FUNC(FRSQRTS, frsqrts);
7364 SIM_FUNC(FMAXNMP, fmaxnmp);
7365 SIM_FUNC(FADDP, faddp);
7366 SIM_FUNC(FMUL, fmul);
7367 SIM_FUNC(FMAXP, fmaxp);
7368 SIM_FUNC(FDIV, fdiv);
7369 SIM_FUNC(FMINNMP, fminnmp);
7370 SIM_FUNC(FABD, fabd);
7371 SIM_FUNC(FMINP, fminp);
7372#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08007373 case NEON_FMLA_H:
7374 fmla(vf, rd, rd, rn, rm);
7375 break;
7376 case NEON_FMLS_H:
7377 fmls(vf, rd, rd, rn, rm);
7378 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007379 case NEON_FCMEQ_H:
7380 fcmp(vf, rd, rn, rm, eq);
7381 break;
7382 case NEON_FCMGE_H:
7383 fcmp(vf, rd, rn, rm, ge);
7384 break;
7385 case NEON_FACGE_H:
7386 fabscmp(vf, rd, rn, rm, ge);
7387 break;
7388 case NEON_FCMGT_H:
7389 fcmp(vf, rd, rn, rm, gt);
7390 break;
7391 case NEON_FACGT_H:
7392 fabscmp(vf, rd, rn, rm, gt);
7393 break;
7394 default:
7395 VIXL_UNIMPLEMENTED();
7396 break;
7397 }
7398}
7399
Carey Williams2809e6c2018-03-13 12:24:16 +00007400void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7401 NEONFormatDecoder nfd(instr);
7402 SimVRegister& rd = ReadVRegister(instr->GetRd());
7403 SimVRegister& rn = ReadVRegister(instr->GetRn());
7404 SimVRegister& rm = ReadVRegister(instr->GetRm());
7405 int rot = 0;
7406 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01007407 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
7408 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01007409 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01007410 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
7411 rot = instr->GetImmRotFcadd();
7412 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01007413 } else {
7414 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01007415 case NEON_SDOT:
7416 sdot(vf, rd, rn, rm);
7417 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007418 case NEON_SQRDMLAH:
7419 sqrdmlah(vf, rd, rn, rm);
7420 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007421 case NEON_UDOT:
7422 udot(vf, rd, rn, rm);
7423 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007424 case NEON_SQRDMLSH:
7425 sqrdmlsh(vf, rd, rn, rm);
7426 break;
7427 default:
7428 VIXL_UNIMPLEMENTED();
7429 break;
7430 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007431 }
7432}
7433
7434
Alexandre Ramesd3832962016-07-04 15:03:43 +01007435void Simulator::VisitNEON3Different(const Instruction* instr) {
7436 NEONFormatDecoder nfd(instr);
7437 VectorFormat vf = nfd.GetVectorFormat();
7438 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7439
7440 SimVRegister& rd = ReadVRegister(instr->GetRd());
7441 SimVRegister& rn = ReadVRegister(instr->GetRn());
7442 SimVRegister& rm = ReadVRegister(instr->GetRm());
7443
7444 switch (instr->Mask(NEON3DifferentMask)) {
7445 case NEON_PMULL:
7446 pmull(vf_l, rd, rn, rm);
7447 break;
7448 case NEON_PMULL2:
7449 pmull2(vf_l, rd, rn, rm);
7450 break;
7451 case NEON_UADDL:
7452 uaddl(vf_l, rd, rn, rm);
7453 break;
7454 case NEON_UADDL2:
7455 uaddl2(vf_l, rd, rn, rm);
7456 break;
7457 case NEON_SADDL:
7458 saddl(vf_l, rd, rn, rm);
7459 break;
7460 case NEON_SADDL2:
7461 saddl2(vf_l, rd, rn, rm);
7462 break;
7463 case NEON_USUBL:
7464 usubl(vf_l, rd, rn, rm);
7465 break;
7466 case NEON_USUBL2:
7467 usubl2(vf_l, rd, rn, rm);
7468 break;
7469 case NEON_SSUBL:
7470 ssubl(vf_l, rd, rn, rm);
7471 break;
7472 case NEON_SSUBL2:
7473 ssubl2(vf_l, rd, rn, rm);
7474 break;
7475 case NEON_SABAL:
7476 sabal(vf_l, rd, rn, rm);
7477 break;
7478 case NEON_SABAL2:
7479 sabal2(vf_l, rd, rn, rm);
7480 break;
7481 case NEON_UABAL:
7482 uabal(vf_l, rd, rn, rm);
7483 break;
7484 case NEON_UABAL2:
7485 uabal2(vf_l, rd, rn, rm);
7486 break;
7487 case NEON_SABDL:
7488 sabdl(vf_l, rd, rn, rm);
7489 break;
7490 case NEON_SABDL2:
7491 sabdl2(vf_l, rd, rn, rm);
7492 break;
7493 case NEON_UABDL:
7494 uabdl(vf_l, rd, rn, rm);
7495 break;
7496 case NEON_UABDL2:
7497 uabdl2(vf_l, rd, rn, rm);
7498 break;
7499 case NEON_SMLAL:
7500 smlal(vf_l, rd, rn, rm);
7501 break;
7502 case NEON_SMLAL2:
7503 smlal2(vf_l, rd, rn, rm);
7504 break;
7505 case NEON_UMLAL:
7506 umlal(vf_l, rd, rn, rm);
7507 break;
7508 case NEON_UMLAL2:
7509 umlal2(vf_l, rd, rn, rm);
7510 break;
7511 case NEON_SMLSL:
7512 smlsl(vf_l, rd, rn, rm);
7513 break;
7514 case NEON_SMLSL2:
7515 smlsl2(vf_l, rd, rn, rm);
7516 break;
7517 case NEON_UMLSL:
7518 umlsl(vf_l, rd, rn, rm);
7519 break;
7520 case NEON_UMLSL2:
7521 umlsl2(vf_l, rd, rn, rm);
7522 break;
7523 case NEON_SMULL:
7524 smull(vf_l, rd, rn, rm);
7525 break;
7526 case NEON_SMULL2:
7527 smull2(vf_l, rd, rn, rm);
7528 break;
7529 case NEON_UMULL:
7530 umull(vf_l, rd, rn, rm);
7531 break;
7532 case NEON_UMULL2:
7533 umull2(vf_l, rd, rn, rm);
7534 break;
7535 case NEON_SQDMLAL:
7536 sqdmlal(vf_l, rd, rn, rm);
7537 break;
7538 case NEON_SQDMLAL2:
7539 sqdmlal2(vf_l, rd, rn, rm);
7540 break;
7541 case NEON_SQDMLSL:
7542 sqdmlsl(vf_l, rd, rn, rm);
7543 break;
7544 case NEON_SQDMLSL2:
7545 sqdmlsl2(vf_l, rd, rn, rm);
7546 break;
7547 case NEON_SQDMULL:
7548 sqdmull(vf_l, rd, rn, rm);
7549 break;
7550 case NEON_SQDMULL2:
7551 sqdmull2(vf_l, rd, rn, rm);
7552 break;
7553 case NEON_UADDW:
7554 uaddw(vf_l, rd, rn, rm);
7555 break;
7556 case NEON_UADDW2:
7557 uaddw2(vf_l, rd, rn, rm);
7558 break;
7559 case NEON_SADDW:
7560 saddw(vf_l, rd, rn, rm);
7561 break;
7562 case NEON_SADDW2:
7563 saddw2(vf_l, rd, rn, rm);
7564 break;
7565 case NEON_USUBW:
7566 usubw(vf_l, rd, rn, rm);
7567 break;
7568 case NEON_USUBW2:
7569 usubw2(vf_l, rd, rn, rm);
7570 break;
7571 case NEON_SSUBW:
7572 ssubw(vf_l, rd, rn, rm);
7573 break;
7574 case NEON_SSUBW2:
7575 ssubw2(vf_l, rd, rn, rm);
7576 break;
7577 case NEON_ADDHN:
7578 addhn(vf, rd, rn, rm);
7579 break;
7580 case NEON_ADDHN2:
7581 addhn2(vf, rd, rn, rm);
7582 break;
7583 case NEON_RADDHN:
7584 raddhn(vf, rd, rn, rm);
7585 break;
7586 case NEON_RADDHN2:
7587 raddhn2(vf, rd, rn, rm);
7588 break;
7589 case NEON_SUBHN:
7590 subhn(vf, rd, rn, rm);
7591 break;
7592 case NEON_SUBHN2:
7593 subhn2(vf, rd, rn, rm);
7594 break;
7595 case NEON_RSUBHN:
7596 rsubhn(vf, rd, rn, rm);
7597 break;
7598 case NEON_RSUBHN2:
7599 rsubhn2(vf, rd, rn, rm);
7600 break;
7601 default:
7602 VIXL_UNIMPLEMENTED();
7603 }
7604}
7605
7606
7607void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7608 NEONFormatDecoder nfd(instr);
7609
Jacob Bramleyca789742018-09-13 14:25:46 +01007610 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7611
Alexandre Ramesd3832962016-07-04 15:03:43 +01007612 SimVRegister& rd = ReadVRegister(instr->GetRd());
7613 SimVRegister& rn = ReadVRegister(instr->GetRn());
7614
Jacob Bramleyca789742018-09-13 14:25:46 +01007615 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7616 VectorFormat vf = nfd.GetVectorFormat(&map_half);
7617 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7618 case NEON_FMAXV_H:
7619 fmaxv(vf, rd, rn);
7620 break;
7621 case NEON_FMINV_H:
7622 fminv(vf, rd, rn);
7623 break;
7624 case NEON_FMAXNMV_H:
7625 fmaxnmv(vf, rd, rn);
7626 break;
7627 case NEON_FMINNMV_H:
7628 fminnmv(vf, rd, rn);
7629 break;
7630 default:
7631 VIXL_UNIMPLEMENTED();
7632 }
7633 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7634 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01007635 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7636
7637 switch (instr->Mask(NEONAcrossLanesFPMask)) {
7638 case NEON_FMAXV:
7639 fmaxv(vf, rd, rn);
7640 break;
7641 case NEON_FMINV:
7642 fminv(vf, rd, rn);
7643 break;
7644 case NEON_FMAXNMV:
7645 fmaxnmv(vf, rd, rn);
7646 break;
7647 case NEON_FMINNMV:
7648 fminnmv(vf, rd, rn);
7649 break;
7650 default:
7651 VIXL_UNIMPLEMENTED();
7652 }
7653 } else {
7654 VectorFormat vf = nfd.GetVectorFormat();
7655
7656 switch (instr->Mask(NEONAcrossLanesMask)) {
7657 case NEON_ADDV:
7658 addv(vf, rd, rn);
7659 break;
7660 case NEON_SMAXV:
7661 smaxv(vf, rd, rn);
7662 break;
7663 case NEON_SMINV:
7664 sminv(vf, rd, rn);
7665 break;
7666 case NEON_UMAXV:
7667 umaxv(vf, rd, rn);
7668 break;
7669 case NEON_UMINV:
7670 uminv(vf, rd, rn);
7671 break;
7672 case NEON_SADDLV:
7673 saddlv(vf, rd, rn);
7674 break;
7675 case NEON_UADDLV:
7676 uaddlv(vf, rd, rn);
7677 break;
7678 default:
7679 VIXL_UNIMPLEMENTED();
7680 }
7681 }
7682}
7683
7684
7685void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7686 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01007687 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007688 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01007689 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007690 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7691
7692 SimVRegister& rd = ReadVRegister(instr->GetRd());
7693 SimVRegister& rn = ReadVRegister(instr->GetRn());
7694
7695 ByElementOp Op = NULL;
7696
7697 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007698 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007699 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007700 int index_hlm = (index << 1) | instr->GetNEONM();
7701
7702 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
7703 // These are oddballs and are best handled as special cases.
7704 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
7705 // - The index is always H:L:M.
7706 case NEON_FMLAL_H_byelement:
7707 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7708 return;
7709 case NEON_FMLAL2_H_byelement:
7710 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7711 return;
7712 case NEON_FMLSL_H_byelement:
7713 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7714 return;
7715 case NEON_FMLSL2_H_byelement:
7716 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7717 return;
7718 }
7719
Alexandre Ramesd3832962016-07-04 15:03:43 +01007720 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007721 rm_reg = rm_low_reg;
7722 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007723 }
7724
7725 switch (instr->Mask(NEONByIndexedElementMask)) {
7726 case NEON_MUL_byelement:
7727 Op = &Simulator::mul;
7728 vf = vf_r;
7729 break;
7730 case NEON_MLA_byelement:
7731 Op = &Simulator::mla;
7732 vf = vf_r;
7733 break;
7734 case NEON_MLS_byelement:
7735 Op = &Simulator::mls;
7736 vf = vf_r;
7737 break;
7738 case NEON_SQDMULH_byelement:
7739 Op = &Simulator::sqdmulh;
7740 vf = vf_r;
7741 break;
7742 case NEON_SQRDMULH_byelement:
7743 Op = &Simulator::sqrdmulh;
7744 vf = vf_r;
7745 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007746 case NEON_SDOT_byelement:
7747 Op = &Simulator::sdot;
7748 vf = vf_r;
7749 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007750 case NEON_SQRDMLAH_byelement:
7751 Op = &Simulator::sqrdmlah;
7752 vf = vf_r;
7753 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007754 case NEON_UDOT_byelement:
7755 Op = &Simulator::udot;
7756 vf = vf_r;
7757 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007758 case NEON_SQRDMLSH_byelement:
7759 Op = &Simulator::sqrdmlsh;
7760 vf = vf_r;
7761 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007762 case NEON_SMULL_byelement:
7763 if (instr->Mask(NEON_Q)) {
7764 Op = &Simulator::smull2;
7765 } else {
7766 Op = &Simulator::smull;
7767 }
7768 break;
7769 case NEON_UMULL_byelement:
7770 if (instr->Mask(NEON_Q)) {
7771 Op = &Simulator::umull2;
7772 } else {
7773 Op = &Simulator::umull;
7774 }
7775 break;
7776 case NEON_SMLAL_byelement:
7777 if (instr->Mask(NEON_Q)) {
7778 Op = &Simulator::smlal2;
7779 } else {
7780 Op = &Simulator::smlal;
7781 }
7782 break;
7783 case NEON_UMLAL_byelement:
7784 if (instr->Mask(NEON_Q)) {
7785 Op = &Simulator::umlal2;
7786 } else {
7787 Op = &Simulator::umlal;
7788 }
7789 break;
7790 case NEON_SMLSL_byelement:
7791 if (instr->Mask(NEON_Q)) {
7792 Op = &Simulator::smlsl2;
7793 } else {
7794 Op = &Simulator::smlsl;
7795 }
7796 break;
7797 case NEON_UMLSL_byelement:
7798 if (instr->Mask(NEON_Q)) {
7799 Op = &Simulator::umlsl2;
7800 } else {
7801 Op = &Simulator::umlsl;
7802 }
7803 break;
7804 case NEON_SQDMULL_byelement:
7805 if (instr->Mask(NEON_Q)) {
7806 Op = &Simulator::sqdmull2;
7807 } else {
7808 Op = &Simulator::sqdmull;
7809 }
7810 break;
7811 case NEON_SQDMLAL_byelement:
7812 if (instr->Mask(NEON_Q)) {
7813 Op = &Simulator::sqdmlal2;
7814 } else {
7815 Op = &Simulator::sqdmlal;
7816 }
7817 break;
7818 case NEON_SQDMLSL_byelement:
7819 if (instr->Mask(NEON_Q)) {
7820 Op = &Simulator::sqdmlsl2;
7821 } else {
7822 Op = &Simulator::sqdmlsl;
7823 }
7824 break;
7825 default:
7826 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01007827 if (instr->GetFPType() == 0) {
7828 rm_reg &= 0xf;
7829 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7830 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007831 index = (index << 1) | instr->GetNEONL();
7832 }
7833
7834 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7835
7836 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01007837 case NEON_FMUL_H_byelement:
7838 vf = vf_half;
7839 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007840 case NEON_FMUL_byelement:
7841 Op = &Simulator::fmul;
7842 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007843 case NEON_FMLA_H_byelement:
7844 vf = vf_half;
7845 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007846 case NEON_FMLA_byelement:
7847 Op = &Simulator::fmla;
7848 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007849 case NEON_FMLS_H_byelement:
7850 vf = vf_half;
7851 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007852 case NEON_FMLS_byelement:
7853 Op = &Simulator::fmls;
7854 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007855 case NEON_FMULX_H_byelement:
7856 vf = vf_half;
7857 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007858 case NEON_FMULX_byelement:
7859 Op = &Simulator::fmulx;
7860 break;
7861 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007862 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00007863 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007864 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00007865 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007866 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007867 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
7868 case NEON_FCMLA_byelement:
7869 vf = vf_r;
7870 fcmla(vf,
7871 rd,
7872 rn,
7873 ReadVRegister(instr->GetRm()),
7874 index,
7875 instr->GetImmRotFcmlaSca());
7876 return;
7877 default:
7878 VIXL_UNIMPLEMENTED();
7879 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007880 }
7881 }
7882
7883 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
7884}
7885
7886
7887void Simulator::VisitNEONCopy(const Instruction* instr) {
7888 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7889 VectorFormat vf = nfd.GetVectorFormat();
7890
7891 SimVRegister& rd = ReadVRegister(instr->GetRd());
7892 SimVRegister& rn = ReadVRegister(instr->GetRn());
7893 int imm5 = instr->GetImmNEON5();
7894 int tz = CountTrailingZeros(imm5, 32);
7895 int reg_index = imm5 >> (tz + 1);
7896
7897 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7898 int imm4 = instr->GetImmNEON4();
7899 int rn_index = imm4 >> tz;
7900 ins_element(vf, rd, reg_index, rn, rn_index);
7901 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7902 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7903 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7904 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7905 value &= MaxUintFromFormat(vf);
7906 WriteXRegister(instr->GetRd(), value);
7907 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7908 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7909 if (instr->GetNEONQ()) {
7910 WriteXRegister(instr->GetRd(), value);
7911 } else {
7912 WriteWRegister(instr->GetRd(), (int32_t)value);
7913 }
7914 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7915 dup_element(vf, rd, rn, reg_index);
7916 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7917 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7918 } else {
7919 VIXL_UNIMPLEMENTED();
7920 }
7921}
7922
7923
7924void Simulator::VisitNEONExtract(const Instruction* instr) {
7925 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7926 VectorFormat vf = nfd.GetVectorFormat();
7927 SimVRegister& rd = ReadVRegister(instr->GetRd());
7928 SimVRegister& rn = ReadVRegister(instr->GetRn());
7929 SimVRegister& rm = ReadVRegister(instr->GetRm());
7930 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7931 int index = instr->GetImmNEONExt();
7932 ext(vf, rd, rn, rm, index);
7933 } else {
7934 VIXL_UNIMPLEMENTED();
7935 }
7936}
7937
7938
7939void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7940 AddrMode addr_mode) {
7941 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7942 VectorFormat vf = nfd.GetVectorFormat();
7943
7944 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7945 int reg_size = RegisterSizeInBytesFromFormat(vf);
7946
7947 int reg[4];
7948 uint64_t addr[4];
7949 for (int i = 0; i < 4; i++) {
7950 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7951 addr[i] = addr_base + (i * reg_size);
7952 }
Jacob Bramley423e5422019-11-13 19:15:55 +00007953 int struct_parts = 1;
7954 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007955 bool log_read = true;
7956
Martyn Capewell32009e32016-10-27 11:00:37 +01007957 // Bit 23 determines whether this is an offset or post-index addressing mode.
7958 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7959 // register or immediate in post-index mode.
7960 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007961 VIXL_UNREACHABLE();
7962 }
7963
7964 // We use the PostIndex mask here, as it works in this case for both Offset
7965 // and PostIndex addressing.
7966 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7967 case NEON_LD1_4v:
7968 case NEON_LD1_4v_post:
7969 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007970 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007971 VIXL_FALLTHROUGH();
7972 case NEON_LD1_3v:
7973 case NEON_LD1_3v_post:
7974 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007975 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007976 VIXL_FALLTHROUGH();
7977 case NEON_LD1_2v:
7978 case NEON_LD1_2v_post:
7979 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007980 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007981 VIXL_FALLTHROUGH();
7982 case NEON_LD1_1v:
7983 case NEON_LD1_1v_post:
7984 ld1(vf, ReadVRegister(reg[0]), addr[0]);
7985 break;
7986 case NEON_ST1_4v:
7987 case NEON_ST1_4v_post:
7988 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007989 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007990 VIXL_FALLTHROUGH();
7991 case NEON_ST1_3v:
7992 case NEON_ST1_3v_post:
7993 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007994 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007995 VIXL_FALLTHROUGH();
7996 case NEON_ST1_2v:
7997 case NEON_ST1_2v_post:
7998 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007999 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008000 VIXL_FALLTHROUGH();
8001 case NEON_ST1_1v:
8002 case NEON_ST1_1v_post:
8003 st1(vf, ReadVRegister(reg[0]), addr[0]);
8004 log_read = false;
8005 break;
8006 case NEON_LD2_post:
8007 case NEON_LD2:
8008 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008009 struct_parts = 2;
8010 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008011 break;
8012 case NEON_ST2:
8013 case NEON_ST2_post:
8014 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008015 struct_parts = 2;
8016 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01008017 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008018 break;
8019 case NEON_LD3_post:
8020 case NEON_LD3:
8021 ld3(vf,
8022 ReadVRegister(reg[0]),
8023 ReadVRegister(reg[1]),
8024 ReadVRegister(reg[2]),
8025 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008026 struct_parts = 3;
8027 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008028 break;
8029 case NEON_ST3:
8030 case NEON_ST3_post:
8031 st3(vf,
8032 ReadVRegister(reg[0]),
8033 ReadVRegister(reg[1]),
8034 ReadVRegister(reg[2]),
8035 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008036 struct_parts = 3;
8037 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01008038 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008039 break;
8040 case NEON_ST4:
8041 case NEON_ST4_post:
8042 st4(vf,
8043 ReadVRegister(reg[0]),
8044 ReadVRegister(reg[1]),
8045 ReadVRegister(reg[2]),
8046 ReadVRegister(reg[3]),
8047 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008048 struct_parts = 4;
8049 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01008050 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008051 break;
8052 case NEON_LD4_post:
8053 case NEON_LD4:
8054 ld4(vf,
8055 ReadVRegister(reg[0]),
8056 ReadVRegister(reg[1]),
8057 ReadVRegister(reg[2]),
8058 ReadVRegister(reg[3]),
8059 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008060 struct_parts = 4;
8061 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008062 break;
8063 default:
8064 VIXL_UNIMPLEMENTED();
8065 }
8066
Jacob Bramley7eb3e212019-11-22 17:28:05 +00008067 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00008068 if (do_trace) {
8069 PrintRegisterFormat print_format =
8070 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8071 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008072 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00008073 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01008074 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00008075 op = "->";
8076 // Stores don't represent a change to the source register's value, so only
8077 // print the relevant part of the value.
8078 print_format = GetPrintRegPartial(print_format);
8079 }
8080
8081 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
8082 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
8083 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
8084 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008085 }
8086 }
8087
8088 if (addr_mode == PostIndex) {
8089 int rm = instr->GetRm();
8090 // The immediate post index addressing mode is indicated by rm = 31.
8091 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00008092 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01008093 : ReadXRegister(rm);
8094 WriteXRegister(instr->GetRn(), addr_base);
8095 } else {
8096 VIXL_ASSERT(addr_mode == Offset);
8097 }
8098}
8099
8100
8101void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8102 NEONLoadStoreMultiStructHelper(instr, Offset);
8103}
8104
8105
8106void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8107 const Instruction* instr) {
8108 NEONLoadStoreMultiStructHelper(instr, PostIndex);
8109}
8110
8111
8112void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8113 AddrMode addr_mode) {
8114 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8115 int rt = instr->GetRt();
8116
Martyn Capewell32009e32016-10-27 11:00:37 +01008117 // Bit 23 determines whether this is an offset or post-index addressing mode.
8118 // In offset mode, bits 20 to 16 should be zero; these bits encode the
8119 // register or immediate in post-index mode.
8120 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008121 VIXL_UNREACHABLE();
8122 }
8123
8124 // We use the PostIndex mask here, as it works in this case for both Offset
8125 // and PostIndex addressing.
8126 bool do_load = false;
8127
Jacob Bramley423e5422019-11-13 19:15:55 +00008128 bool replicating = false;
8129
Alexandre Ramesd3832962016-07-04 15:03:43 +01008130 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8131 VectorFormat vf_t = nfd.GetVectorFormat();
8132
8133 VectorFormat vf = kFormat16B;
8134 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8135 case NEON_LD1_b:
8136 case NEON_LD1_b_post:
8137 case NEON_LD2_b:
8138 case NEON_LD2_b_post:
8139 case NEON_LD3_b:
8140 case NEON_LD3_b_post:
8141 case NEON_LD4_b:
8142 case NEON_LD4_b_post:
8143 do_load = true;
8144 VIXL_FALLTHROUGH();
8145 case NEON_ST1_b:
8146 case NEON_ST1_b_post:
8147 case NEON_ST2_b:
8148 case NEON_ST2_b_post:
8149 case NEON_ST3_b:
8150 case NEON_ST3_b_post:
8151 case NEON_ST4_b:
8152 case NEON_ST4_b_post:
8153 break;
8154
8155 case NEON_LD1_h:
8156 case NEON_LD1_h_post:
8157 case NEON_LD2_h:
8158 case NEON_LD2_h_post:
8159 case NEON_LD3_h:
8160 case NEON_LD3_h_post:
8161 case NEON_LD4_h:
8162 case NEON_LD4_h_post:
8163 do_load = true;
8164 VIXL_FALLTHROUGH();
8165 case NEON_ST1_h:
8166 case NEON_ST1_h_post:
8167 case NEON_ST2_h:
8168 case NEON_ST2_h_post:
8169 case NEON_ST3_h:
8170 case NEON_ST3_h_post:
8171 case NEON_ST4_h:
8172 case NEON_ST4_h_post:
8173 vf = kFormat8H;
8174 break;
8175 case NEON_LD1_s:
8176 case NEON_LD1_s_post:
8177 case NEON_LD2_s:
8178 case NEON_LD2_s_post:
8179 case NEON_LD3_s:
8180 case NEON_LD3_s_post:
8181 case NEON_LD4_s:
8182 case NEON_LD4_s_post:
8183 do_load = true;
8184 VIXL_FALLTHROUGH();
8185 case NEON_ST1_s:
8186 case NEON_ST1_s_post:
8187 case NEON_ST2_s:
8188 case NEON_ST2_s_post:
8189 case NEON_ST3_s:
8190 case NEON_ST3_s_post:
8191 case NEON_ST4_s:
8192 case NEON_ST4_s_post: {
8193 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8194 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8195 NEON_LD1_d_post);
8196 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8197 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8198 NEON_ST1_d_post);
8199 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8200 break;
8201 }
8202
8203 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008204 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008205 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008206 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008207 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008208 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008209 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008210 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008211 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008212 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00008213 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008214 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00008215
Alexandre Ramesd3832962016-07-04 15:03:43 +01008216 default:
8217 VIXL_UNIMPLEMENTED();
8218 }
8219
Alexandre Ramesd3832962016-07-04 15:03:43 +01008220 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8221 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00008222 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008223 int rt2 = (rt + 1) % kNumberOfVRegisters;
8224 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8225 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8226 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8227 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00008228 reg_count = 1;
8229 if (replicating) {
8230 VIXL_ASSERT(do_load);
8231 ld1r(vf, ReadVRegister(rt), addr);
8232 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008233 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008234 } else {
8235 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008236 }
8237 break;
8238 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00008239 reg_count = 2;
8240 if (replicating) {
8241 VIXL_ASSERT(do_load);
8242 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8243 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008244 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008245 } else {
8246 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008247 }
8248 break;
8249 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00008250 reg_count = 3;
8251 if (replicating) {
8252 VIXL_ASSERT(do_load);
8253 ld3r(vf,
8254 ReadVRegister(rt),
8255 ReadVRegister(rt2),
8256 ReadVRegister(rt3),
8257 addr);
8258 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008259 ld3(vf,
8260 ReadVRegister(rt),
8261 ReadVRegister(rt2),
8262 ReadVRegister(rt3),
8263 lane,
8264 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008265 } else {
8266 st3(vf,
8267 ReadVRegister(rt),
8268 ReadVRegister(rt2),
8269 ReadVRegister(rt3),
8270 lane,
8271 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008272 }
8273 break;
8274 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00008275 reg_count = 4;
8276 if (replicating) {
8277 VIXL_ASSERT(do_load);
8278 ld4r(vf,
8279 ReadVRegister(rt),
8280 ReadVRegister(rt2),
8281 ReadVRegister(rt3),
8282 ReadVRegister(rt4),
8283 addr);
8284 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008285 ld4(vf,
8286 ReadVRegister(rt),
8287 ReadVRegister(rt2),
8288 ReadVRegister(rt3),
8289 ReadVRegister(rt4),
8290 lane,
8291 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008292 } else {
8293 st4(vf,
8294 ReadVRegister(rt),
8295 ReadVRegister(rt2),
8296 ReadVRegister(rt3),
8297 ReadVRegister(rt4),
8298 lane,
8299 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008300 }
8301 break;
8302 default:
8303 VIXL_UNIMPLEMENTED();
8304 }
8305
Jacob Bramley423e5422019-11-13 19:15:55 +00008306 // Trace registers and/or memory writes.
8307 PrintRegisterFormat print_format =
8308 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8309 if (do_load) {
8310 if (ShouldTraceVRegs()) {
8311 if (replicating) {
8312 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8313 } else {
8314 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8315 }
8316 }
8317 } else {
8318 if (ShouldTraceWrites()) {
8319 // Stores don't represent a change to the source register's value, so only
8320 // print the relevant part of the value.
8321 print_format = GetPrintRegPartial(print_format);
8322 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8323 }
8324 }
8325
Alexandre Ramesd3832962016-07-04 15:03:43 +01008326 if (addr_mode == PostIndex) {
8327 int rm = instr->GetRm();
8328 int lane_size = LaneSizeInBytesFromFormat(vf);
8329 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00008330 addr + ((rm == 31) ? (reg_count * lane_size)
8331 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008332 }
8333}
8334
8335
8336void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8337 NEONLoadStoreSingleStructHelper(instr, Offset);
8338}
8339
8340
8341void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8342 const Instruction* instr) {
8343 NEONLoadStoreSingleStructHelper(instr, PostIndex);
8344}
8345
8346
8347void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8348 SimVRegister& rd = ReadVRegister(instr->GetRd());
8349 int cmode = instr->GetNEONCmode();
8350 int cmode_3_1 = (cmode >> 1) & 7;
8351 int cmode_3 = (cmode >> 3) & 1;
8352 int cmode_2 = (cmode >> 2) & 1;
8353 int cmode_1 = (cmode >> 1) & 1;
8354 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01008355 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008356 int q = instr->GetNEONQ();
8357 int op_bit = instr->GetNEONModImmOp();
8358 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01008359 // Find the format and immediate value
8360 uint64_t imm = 0;
8361 VectorFormat vform = kFormatUndefined;
8362 switch (cmode_3_1) {
8363 case 0x0:
8364 case 0x1:
8365 case 0x2:
8366 case 0x3:
8367 vform = (q == 1) ? kFormat4S : kFormat2S;
8368 imm = imm8 << (8 * cmode_3_1);
8369 break;
8370 case 0x4:
8371 case 0x5:
8372 vform = (q == 1) ? kFormat8H : kFormat4H;
8373 imm = imm8 << (8 * cmode_1);
8374 break;
8375 case 0x6:
8376 vform = (q == 1) ? kFormat4S : kFormat2S;
8377 if (cmode_0 == 0) {
8378 imm = imm8 << 8 | 0x000000ff;
8379 } else {
8380 imm = imm8 << 16 | 0x0000ffff;
8381 }
8382 break;
8383 case 0x7:
8384 if (cmode_0 == 0 && op_bit == 0) {
8385 vform = q ? kFormat16B : kFormat8B;
8386 imm = imm8;
8387 } else if (cmode_0 == 0 && op_bit == 1) {
8388 vform = q ? kFormat2D : kFormat1D;
8389 imm = 0;
8390 for (int i = 0; i < 8; ++i) {
8391 if (imm8 & (1 << i)) {
8392 imm |= (UINT64_C(0xff) << (8 * i));
8393 }
8394 }
8395 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01008396 if (half_enc == 1) {
8397 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01008398 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01008399 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008400 vform = q ? kFormat4S : kFormat2S;
8401 imm = FloatToRawbits(instr->GetImmNEONFP32());
8402 } else if (q == 1) {
8403 vform = kFormat2D;
8404 imm = DoubleToRawbits(instr->GetImmNEONFP64());
8405 } else {
8406 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8407 VisitUnallocated(instr);
8408 }
8409 }
8410 break;
8411 default:
8412 VIXL_UNREACHABLE();
8413 break;
8414 }
8415
8416 // Find the operation
8417 NEONModifiedImmediateOp op;
8418 if (cmode_3 == 0) {
8419 if (cmode_0 == 0) {
8420 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8421 } else { // cmode<0> == '1'
8422 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8423 }
8424 } else { // cmode<3> == '1'
8425 if (cmode_2 == 0) {
8426 if (cmode_0 == 0) {
8427 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8428 } else { // cmode<0> == '1'
8429 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8430 }
8431 } else { // cmode<2> == '1'
8432 if (cmode_1 == 0) {
8433 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8434 } else { // cmode<1> == '1'
8435 if (cmode_0 == 0) {
8436 op = NEONModifiedImmediate_MOVI;
8437 } else { // cmode<0> == '1'
8438 op = NEONModifiedImmediate_MOVI;
8439 }
8440 }
8441 }
8442 }
8443
8444 // Call the logic function
8445 if (op == NEONModifiedImmediate_ORR) {
8446 orr(vform, rd, rd, imm);
8447 } else if (op == NEONModifiedImmediate_BIC) {
8448 bic(vform, rd, rd, imm);
8449 } else if (op == NEONModifiedImmediate_MOVI) {
8450 movi(vform, rd, imm);
8451 } else if (op == NEONModifiedImmediate_MVNI) {
8452 mvni(vform, rd, imm);
8453 } else {
8454 VisitUnimplemented(instr);
8455 }
8456}
8457
8458
8459void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8460 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8461 VectorFormat vf = nfd.GetVectorFormat();
8462
8463 SimVRegister& rd = ReadVRegister(instr->GetRd());
8464 SimVRegister& rn = ReadVRegister(instr->GetRn());
8465
8466 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8467 // These instructions all use a two bit size field, except NOT and RBIT,
8468 // which use the field to encode the operation.
8469 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8470 case NEON_CMEQ_zero_scalar:
8471 cmp(vf, rd, rn, 0, eq);
8472 break;
8473 case NEON_CMGE_zero_scalar:
8474 cmp(vf, rd, rn, 0, ge);
8475 break;
8476 case NEON_CMGT_zero_scalar:
8477 cmp(vf, rd, rn, 0, gt);
8478 break;
8479 case NEON_CMLT_zero_scalar:
8480 cmp(vf, rd, rn, 0, lt);
8481 break;
8482 case NEON_CMLE_zero_scalar:
8483 cmp(vf, rd, rn, 0, le);
8484 break;
8485 case NEON_ABS_scalar:
8486 abs(vf, rd, rn);
8487 break;
8488 case NEON_SQABS_scalar:
8489 abs(vf, rd, rn).SignedSaturate(vf);
8490 break;
8491 case NEON_NEG_scalar:
8492 neg(vf, rd, rn);
8493 break;
8494 case NEON_SQNEG_scalar:
8495 neg(vf, rd, rn).SignedSaturate(vf);
8496 break;
8497 case NEON_SUQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008498 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008499 break;
8500 case NEON_USQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008501 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008502 break;
8503 default:
8504 VIXL_UNIMPLEMENTED();
8505 break;
8506 }
8507 } else {
8508 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8509 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8510
8511 // These instructions all use a one bit size field, except SQXTUN, SQXTN
8512 // and UQXTN, which use a two bit size field.
8513 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8514 case NEON_FRECPE_scalar:
8515 frecpe(fpf, rd, rn, fpcr_rounding);
8516 break;
8517 case NEON_FRECPX_scalar:
8518 frecpx(fpf, rd, rn);
8519 break;
8520 case NEON_FRSQRTE_scalar:
8521 frsqrte(fpf, rd, rn);
8522 break;
8523 case NEON_FCMGT_zero_scalar:
8524 fcmp_zero(fpf, rd, rn, gt);
8525 break;
8526 case NEON_FCMGE_zero_scalar:
8527 fcmp_zero(fpf, rd, rn, ge);
8528 break;
8529 case NEON_FCMEQ_zero_scalar:
8530 fcmp_zero(fpf, rd, rn, eq);
8531 break;
8532 case NEON_FCMLE_zero_scalar:
8533 fcmp_zero(fpf, rd, rn, le);
8534 break;
8535 case NEON_FCMLT_zero_scalar:
8536 fcmp_zero(fpf, rd, rn, lt);
8537 break;
8538 case NEON_SCVTF_scalar:
8539 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8540 break;
8541 case NEON_UCVTF_scalar:
8542 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8543 break;
8544 case NEON_FCVTNS_scalar:
8545 fcvts(fpf, rd, rn, FPTieEven);
8546 break;
8547 case NEON_FCVTNU_scalar:
8548 fcvtu(fpf, rd, rn, FPTieEven);
8549 break;
8550 case NEON_FCVTPS_scalar:
8551 fcvts(fpf, rd, rn, FPPositiveInfinity);
8552 break;
8553 case NEON_FCVTPU_scalar:
8554 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8555 break;
8556 case NEON_FCVTMS_scalar:
8557 fcvts(fpf, rd, rn, FPNegativeInfinity);
8558 break;
8559 case NEON_FCVTMU_scalar:
8560 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8561 break;
8562 case NEON_FCVTZS_scalar:
8563 fcvts(fpf, rd, rn, FPZero);
8564 break;
8565 case NEON_FCVTZU_scalar:
8566 fcvtu(fpf, rd, rn, FPZero);
8567 break;
8568 case NEON_FCVTAS_scalar:
8569 fcvts(fpf, rd, rn, FPTieAway);
8570 break;
8571 case NEON_FCVTAU_scalar:
8572 fcvtu(fpf, rd, rn, FPTieAway);
8573 break;
8574 case NEON_FCVTXN_scalar:
8575 // Unlike all of the other FP instructions above, fcvtxn encodes dest
8576 // size S as size<0>=1. There's only one case, so we ignore the form.
8577 VIXL_ASSERT(instr->ExtractBit(22) == 1);
8578 fcvtxn(kFormatS, rd, rn);
8579 break;
8580 default:
8581 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8582 case NEON_SQXTN_scalar:
8583 sqxtn(vf, rd, rn);
8584 break;
8585 case NEON_UQXTN_scalar:
8586 uqxtn(vf, rd, rn);
8587 break;
8588 case NEON_SQXTUN_scalar:
8589 sqxtun(vf, rd, rn);
8590 break;
8591 default:
8592 VIXL_UNIMPLEMENTED();
8593 }
8594 }
8595 }
8596}
8597
8598
Jacob Bramleyca789742018-09-13 14:25:46 +01008599void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8600 VectorFormat fpf = kFormatH;
8601 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8602
8603 SimVRegister& rd = ReadVRegister(instr->GetRd());
8604 SimVRegister& rn = ReadVRegister(instr->GetRn());
8605
8606 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8607 case NEON_FRECPE_H_scalar:
8608 frecpe(fpf, rd, rn, fpcr_rounding);
8609 break;
8610 case NEON_FRECPX_H_scalar:
8611 frecpx(fpf, rd, rn);
8612 break;
8613 case NEON_FRSQRTE_H_scalar:
8614 frsqrte(fpf, rd, rn);
8615 break;
8616 case NEON_FCMGT_H_zero_scalar:
8617 fcmp_zero(fpf, rd, rn, gt);
8618 break;
8619 case NEON_FCMGE_H_zero_scalar:
8620 fcmp_zero(fpf, rd, rn, ge);
8621 break;
8622 case NEON_FCMEQ_H_zero_scalar:
8623 fcmp_zero(fpf, rd, rn, eq);
8624 break;
8625 case NEON_FCMLE_H_zero_scalar:
8626 fcmp_zero(fpf, rd, rn, le);
8627 break;
8628 case NEON_FCMLT_H_zero_scalar:
8629 fcmp_zero(fpf, rd, rn, lt);
8630 break;
8631 case NEON_SCVTF_H_scalar:
8632 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8633 break;
8634 case NEON_UCVTF_H_scalar:
8635 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8636 break;
8637 case NEON_FCVTNS_H_scalar:
8638 fcvts(fpf, rd, rn, FPTieEven);
8639 break;
8640 case NEON_FCVTNU_H_scalar:
8641 fcvtu(fpf, rd, rn, FPTieEven);
8642 break;
8643 case NEON_FCVTPS_H_scalar:
8644 fcvts(fpf, rd, rn, FPPositiveInfinity);
8645 break;
8646 case NEON_FCVTPU_H_scalar:
8647 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8648 break;
8649 case NEON_FCVTMS_H_scalar:
8650 fcvts(fpf, rd, rn, FPNegativeInfinity);
8651 break;
8652 case NEON_FCVTMU_H_scalar:
8653 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8654 break;
8655 case NEON_FCVTZS_H_scalar:
8656 fcvts(fpf, rd, rn, FPZero);
8657 break;
8658 case NEON_FCVTZU_H_scalar:
8659 fcvtu(fpf, rd, rn, FPZero);
8660 break;
8661 case NEON_FCVTAS_H_scalar:
8662 fcvts(fpf, rd, rn, FPTieAway);
8663 break;
8664 case NEON_FCVTAU_H_scalar:
8665 fcvtu(fpf, rd, rn, FPTieAway);
8666 break;
8667 }
8668}
8669
8670
Alexandre Ramesd3832962016-07-04 15:03:43 +01008671void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8672 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8673 VectorFormat vf = nfd.GetVectorFormat();
8674
8675 SimVRegister& rd = ReadVRegister(instr->GetRd());
8676 SimVRegister& rn = ReadVRegister(instr->GetRn());
8677 SimVRegister& rm = ReadVRegister(instr->GetRm());
8678 switch (instr->Mask(NEONScalar3DiffMask)) {
8679 case NEON_SQDMLAL_scalar:
8680 sqdmlal(vf, rd, rn, rm);
8681 break;
8682 case NEON_SQDMLSL_scalar:
8683 sqdmlsl(vf, rd, rn, rm);
8684 break;
8685 case NEON_SQDMULL_scalar:
8686 sqdmull(vf, rd, rn, rm);
8687 break;
8688 default:
8689 VIXL_UNIMPLEMENTED();
8690 }
8691}
8692
8693
8694void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8695 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8696 VectorFormat vf = nfd.GetVectorFormat();
8697
8698 SimVRegister& rd = ReadVRegister(instr->GetRd());
8699 SimVRegister& rn = ReadVRegister(instr->GetRn());
8700 SimVRegister& rm = ReadVRegister(instr->GetRm());
8701
8702 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8703 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8704 switch (instr->Mask(NEONScalar3SameFPMask)) {
8705 case NEON_FMULX_scalar:
8706 fmulx(vf, rd, rn, rm);
8707 break;
8708 case NEON_FACGE_scalar:
8709 fabscmp(vf, rd, rn, rm, ge);
8710 break;
8711 case NEON_FACGT_scalar:
8712 fabscmp(vf, rd, rn, rm, gt);
8713 break;
8714 case NEON_FCMEQ_scalar:
8715 fcmp(vf, rd, rn, rm, eq);
8716 break;
8717 case NEON_FCMGE_scalar:
8718 fcmp(vf, rd, rn, rm, ge);
8719 break;
8720 case NEON_FCMGT_scalar:
8721 fcmp(vf, rd, rn, rm, gt);
8722 break;
8723 case NEON_FRECPS_scalar:
8724 frecps(vf, rd, rn, rm);
8725 break;
8726 case NEON_FRSQRTS_scalar:
8727 frsqrts(vf, rd, rn, rm);
8728 break;
8729 case NEON_FABD_scalar:
8730 fabd(vf, rd, rn, rm);
8731 break;
8732 default:
8733 VIXL_UNIMPLEMENTED();
8734 }
8735 } else {
8736 switch (instr->Mask(NEONScalar3SameMask)) {
8737 case NEON_ADD_scalar:
8738 add(vf, rd, rn, rm);
8739 break;
8740 case NEON_SUB_scalar:
8741 sub(vf, rd, rn, rm);
8742 break;
8743 case NEON_CMEQ_scalar:
8744 cmp(vf, rd, rn, rm, eq);
8745 break;
8746 case NEON_CMGE_scalar:
8747 cmp(vf, rd, rn, rm, ge);
8748 break;
8749 case NEON_CMGT_scalar:
8750 cmp(vf, rd, rn, rm, gt);
8751 break;
8752 case NEON_CMHI_scalar:
8753 cmp(vf, rd, rn, rm, hi);
8754 break;
8755 case NEON_CMHS_scalar:
8756 cmp(vf, rd, rn, rm, hs);
8757 break;
8758 case NEON_CMTST_scalar:
8759 cmptst(vf, rd, rn, rm);
8760 break;
8761 case NEON_USHL_scalar:
8762 ushl(vf, rd, rn, rm);
8763 break;
8764 case NEON_SSHL_scalar:
8765 sshl(vf, rd, rn, rm);
8766 break;
8767 case NEON_SQDMULH_scalar:
8768 sqdmulh(vf, rd, rn, rm);
8769 break;
8770 case NEON_SQRDMULH_scalar:
8771 sqrdmulh(vf, rd, rn, rm);
8772 break;
8773 case NEON_UQADD_scalar:
8774 add(vf, rd, rn, rm).UnsignedSaturate(vf);
8775 break;
8776 case NEON_SQADD_scalar:
8777 add(vf, rd, rn, rm).SignedSaturate(vf);
8778 break;
8779 case NEON_UQSUB_scalar:
8780 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8781 break;
8782 case NEON_SQSUB_scalar:
8783 sub(vf, rd, rn, rm).SignedSaturate(vf);
8784 break;
8785 case NEON_UQSHL_scalar:
8786 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8787 break;
8788 case NEON_SQSHL_scalar:
8789 sshl(vf, rd, rn, rm).SignedSaturate(vf);
8790 break;
8791 case NEON_URSHL_scalar:
8792 ushl(vf, rd, rn, rm).Round(vf);
8793 break;
8794 case NEON_SRSHL_scalar:
8795 sshl(vf, rd, rn, rm).Round(vf);
8796 break;
8797 case NEON_UQRSHL_scalar:
8798 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8799 break;
8800 case NEON_SQRSHL_scalar:
8801 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8802 break;
8803 default:
8804 VIXL_UNIMPLEMENTED();
8805 }
8806 }
8807}
8808
Jacob Bramleyca789742018-09-13 14:25:46 +01008809void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8810 SimVRegister& rd = ReadVRegister(instr->GetRd());
8811 SimVRegister& rn = ReadVRegister(instr->GetRn());
8812 SimVRegister& rm = ReadVRegister(instr->GetRm());
8813
8814 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8815 case NEON_FABD_H_scalar:
8816 fabd(kFormatH, rd, rn, rm);
8817 break;
8818 case NEON_FMULX_H_scalar:
8819 fmulx(kFormatH, rd, rn, rm);
8820 break;
8821 case NEON_FCMEQ_H_scalar:
8822 fcmp(kFormatH, rd, rn, rm, eq);
8823 break;
8824 case NEON_FCMGE_H_scalar:
8825 fcmp(kFormatH, rd, rn, rm, ge);
8826 break;
8827 case NEON_FCMGT_H_scalar:
8828 fcmp(kFormatH, rd, rn, rm, gt);
8829 break;
8830 case NEON_FACGE_H_scalar:
8831 fabscmp(kFormatH, rd, rn, rm, ge);
8832 break;
8833 case NEON_FACGT_H_scalar:
8834 fabscmp(kFormatH, rd, rn, rm, gt);
8835 break;
8836 case NEON_FRECPS_H_scalar:
8837 frecps(kFormatH, rd, rn, rm);
8838 break;
8839 case NEON_FRSQRTS_H_scalar:
8840 frsqrts(kFormatH, rd, rn, rm);
8841 break;
8842 default:
8843 VIXL_UNREACHABLE();
8844 }
8845}
8846
Alexandre Ramesd3832962016-07-04 15:03:43 +01008847
Alexander Gilday43785642018-04-04 13:42:33 +01008848void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8849 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8850 VectorFormat vf = nfd.GetVectorFormat();
8851
8852 SimVRegister& rd = ReadVRegister(instr->GetRd());
8853 SimVRegister& rn = ReadVRegister(instr->GetRn());
8854 SimVRegister& rm = ReadVRegister(instr->GetRm());
8855
8856 switch (instr->Mask(NEONScalar3SameExtraMask)) {
8857 case NEON_SQRDMLAH_scalar:
8858 sqrdmlah(vf, rd, rn, rm);
8859 break;
8860 case NEON_SQRDMLSH_scalar:
8861 sqrdmlsh(vf, rd, rn, rm);
8862 break;
8863 default:
8864 VIXL_UNIMPLEMENTED();
8865 }
8866}
8867
Alexandre Ramesd3832962016-07-04 15:03:43 +01008868void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8869 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8870 VectorFormat vf = nfd.GetVectorFormat();
8871 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8872
8873 SimVRegister& rd = ReadVRegister(instr->GetRd());
8874 SimVRegister& rn = ReadVRegister(instr->GetRn());
8875 ByElementOp Op = NULL;
8876
8877 int rm_reg = instr->GetRm();
8878 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8879 if (instr->GetNEONSize() == 1) {
8880 rm_reg &= 0xf;
8881 index = (index << 1) | instr->GetNEONM();
8882 }
8883
8884 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8885 case NEON_SQDMULL_byelement_scalar:
8886 Op = &Simulator::sqdmull;
8887 break;
8888 case NEON_SQDMLAL_byelement_scalar:
8889 Op = &Simulator::sqdmlal;
8890 break;
8891 case NEON_SQDMLSL_byelement_scalar:
8892 Op = &Simulator::sqdmlsl;
8893 break;
8894 case NEON_SQDMULH_byelement_scalar:
8895 Op = &Simulator::sqdmulh;
8896 vf = vf_r;
8897 break;
8898 case NEON_SQRDMULH_byelement_scalar:
8899 Op = &Simulator::sqrdmulh;
8900 vf = vf_r;
8901 break;
Alexander Gilday43785642018-04-04 13:42:33 +01008902 case NEON_SQRDMLAH_byelement_scalar:
8903 Op = &Simulator::sqrdmlah;
8904 vf = vf_r;
8905 break;
8906 case NEON_SQRDMLSH_byelement_scalar:
8907 Op = &Simulator::sqrdmlsh;
8908 vf = vf_r;
8909 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008910 default:
8911 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8912 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01008913 if (instr->GetFPType() == 0) {
8914 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8915 rm_reg &= 0xf;
8916 vf = kFormatH;
8917 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008918 index = (index << 1) | instr->GetNEONL();
8919 }
8920 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008921 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008922 case NEON_FMUL_byelement_scalar:
8923 Op = &Simulator::fmul;
8924 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008925 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008926 case NEON_FMLA_byelement_scalar:
8927 Op = &Simulator::fmla;
8928 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008929 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008930 case NEON_FMLS_byelement_scalar:
8931 Op = &Simulator::fmls;
8932 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008933 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008934 case NEON_FMULX_byelement_scalar:
8935 Op = &Simulator::fmulx;
8936 break;
8937 default:
8938 VIXL_UNIMPLEMENTED();
8939 }
8940 }
8941
8942 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8943}
8944
8945
8946void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8947 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8948 VectorFormat vf = nfd.GetVectorFormat();
8949
8950 SimVRegister& rd = ReadVRegister(instr->GetRd());
8951 SimVRegister& rn = ReadVRegister(instr->GetRn());
8952
8953 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8954 int imm5 = instr->GetImmNEON5();
8955 int tz = CountTrailingZeros(imm5, 32);
8956 int rn_index = imm5 >> (tz + 1);
8957 dup_element(vf, rd, rn, rn_index);
8958 } else {
8959 VIXL_UNIMPLEMENTED();
8960 }
8961}
8962
8963
8964void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008965 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008966 VectorFormat vf = nfd.GetVectorFormat();
8967
8968 SimVRegister& rd = ReadVRegister(instr->GetRd());
8969 SimVRegister& rn = ReadVRegister(instr->GetRn());
8970 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008971 case NEON_ADDP_scalar: {
8972 // All pairwise operations except ADDP use bit U to differentiate FP16
8973 // from FP32/FP64 variations.
8974 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8975 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008976 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008977 }
8978 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008979 case NEON_FADDP_scalar:
8980 faddp(vf, rd, rn);
8981 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008982 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008983 case NEON_FMAXP_scalar:
8984 fmaxp(vf, rd, rn);
8985 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008986 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008987 case NEON_FMAXNMP_scalar:
8988 fmaxnmp(vf, rd, rn);
8989 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008990 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008991 case NEON_FMINP_scalar:
8992 fminp(vf, rd, rn);
8993 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008994 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008995 case NEON_FMINNMP_scalar:
8996 fminnmp(vf, rd, rn);
8997 break;
8998 default:
8999 VIXL_UNIMPLEMENTED();
9000 }
9001}
9002
9003
9004void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
9005 SimVRegister& rd = ReadVRegister(instr->GetRd());
9006 SimVRegister& rn = ReadVRegister(instr->GetRn());
9007 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9008
9009 static const NEONFormatMap map = {{22, 21, 20, 19},
9010 {NF_UNDEF,
9011 NF_B,
9012 NF_H,
9013 NF_H,
9014 NF_S,
9015 NF_S,
9016 NF_S,
9017 NF_S,
9018 NF_D,
9019 NF_D,
9020 NF_D,
9021 NF_D,
9022 NF_D,
9023 NF_D,
9024 NF_D,
9025 NF_D}};
9026 NEONFormatDecoder nfd(instr, &map);
9027 VectorFormat vf = nfd.GetVectorFormat();
9028
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00009029 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9030 int immh_immb = instr->GetImmNEONImmhImmb();
9031 int right_shift = (16 << highest_set_bit) - immh_immb;
9032 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009033 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
9034 case NEON_SHL_scalar:
9035 shl(vf, rd, rn, left_shift);
9036 break;
9037 case NEON_SLI_scalar:
9038 sli(vf, rd, rn, left_shift);
9039 break;
9040 case NEON_SQSHL_imm_scalar:
9041 sqshl(vf, rd, rn, left_shift);
9042 break;
9043 case NEON_UQSHL_imm_scalar:
9044 uqshl(vf, rd, rn, left_shift);
9045 break;
9046 case NEON_SQSHLU_scalar:
9047 sqshlu(vf, rd, rn, left_shift);
9048 break;
9049 case NEON_SRI_scalar:
9050 sri(vf, rd, rn, right_shift);
9051 break;
9052 case NEON_SSHR_scalar:
9053 sshr(vf, rd, rn, right_shift);
9054 break;
9055 case NEON_USHR_scalar:
9056 ushr(vf, rd, rn, right_shift);
9057 break;
9058 case NEON_SRSHR_scalar:
9059 sshr(vf, rd, rn, right_shift).Round(vf);
9060 break;
9061 case NEON_URSHR_scalar:
9062 ushr(vf, rd, rn, right_shift).Round(vf);
9063 break;
9064 case NEON_SSRA_scalar:
9065 ssra(vf, rd, rn, right_shift);
9066 break;
9067 case NEON_USRA_scalar:
9068 usra(vf, rd, rn, right_shift);
9069 break;
9070 case NEON_SRSRA_scalar:
9071 srsra(vf, rd, rn, right_shift);
9072 break;
9073 case NEON_URSRA_scalar:
9074 ursra(vf, rd, rn, right_shift);
9075 break;
9076 case NEON_UQSHRN_scalar:
9077 uqshrn(vf, rd, rn, right_shift);
9078 break;
9079 case NEON_UQRSHRN_scalar:
9080 uqrshrn(vf, rd, rn, right_shift);
9081 break;
9082 case NEON_SQSHRN_scalar:
9083 sqshrn(vf, rd, rn, right_shift);
9084 break;
9085 case NEON_SQRSHRN_scalar:
9086 sqrshrn(vf, rd, rn, right_shift);
9087 break;
9088 case NEON_SQSHRUN_scalar:
9089 sqshrun(vf, rd, rn, right_shift);
9090 break;
9091 case NEON_SQRSHRUN_scalar:
9092 sqrshrun(vf, rd, rn, right_shift);
9093 break;
9094 case NEON_FCVTZS_imm_scalar:
9095 fcvts(vf, rd, rn, FPZero, right_shift);
9096 break;
9097 case NEON_FCVTZU_imm_scalar:
9098 fcvtu(vf, rd, rn, FPZero, right_shift);
9099 break;
9100 case NEON_SCVTF_imm_scalar:
9101 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9102 break;
9103 case NEON_UCVTF_imm_scalar:
9104 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9105 break;
9106 default:
9107 VIXL_UNIMPLEMENTED();
9108 }
9109}
9110
9111
9112void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9113 SimVRegister& rd = ReadVRegister(instr->GetRd());
9114 SimVRegister& rn = ReadVRegister(instr->GetRn());
9115 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9116
9117 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9118 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9119 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01009120 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
9121 NF_4H, NF_8H, NF_4H, NF_8H,
9122 NF_2S, NF_4S, NF_2S, NF_4S,
9123 NF_2S, NF_4S, NF_2S, NF_4S,
9124 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9125 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9126 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9127 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01009128 NEONFormatDecoder nfd(instr, &map);
9129 VectorFormat vf = nfd.GetVectorFormat();
9130
9131 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9132 static const NEONFormatMap map_l =
9133 {{22, 21, 20, 19},
9134 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9135 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9136
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00009137 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9138 int immh_immb = instr->GetImmNEONImmhImmb();
9139 int right_shift = (16 << highest_set_bit) - immh_immb;
9140 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009141
9142 switch (instr->Mask(NEONShiftImmediateMask)) {
9143 case NEON_SHL:
9144 shl(vf, rd, rn, left_shift);
9145 break;
9146 case NEON_SLI:
9147 sli(vf, rd, rn, left_shift);
9148 break;
9149 case NEON_SQSHLU:
9150 sqshlu(vf, rd, rn, left_shift);
9151 break;
9152 case NEON_SRI:
9153 sri(vf, rd, rn, right_shift);
9154 break;
9155 case NEON_SSHR:
9156 sshr(vf, rd, rn, right_shift);
9157 break;
9158 case NEON_USHR:
9159 ushr(vf, rd, rn, right_shift);
9160 break;
9161 case NEON_SRSHR:
9162 sshr(vf, rd, rn, right_shift).Round(vf);
9163 break;
9164 case NEON_URSHR:
9165 ushr(vf, rd, rn, right_shift).Round(vf);
9166 break;
9167 case NEON_SSRA:
9168 ssra(vf, rd, rn, right_shift);
9169 break;
9170 case NEON_USRA:
9171 usra(vf, rd, rn, right_shift);
9172 break;
9173 case NEON_SRSRA:
9174 srsra(vf, rd, rn, right_shift);
9175 break;
9176 case NEON_URSRA:
9177 ursra(vf, rd, rn, right_shift);
9178 break;
9179 case NEON_SQSHL_imm:
9180 sqshl(vf, rd, rn, left_shift);
9181 break;
9182 case NEON_UQSHL_imm:
9183 uqshl(vf, rd, rn, left_shift);
9184 break;
9185 case NEON_SCVTF_imm:
9186 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9187 break;
9188 case NEON_UCVTF_imm:
9189 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9190 break;
9191 case NEON_FCVTZS_imm:
9192 fcvts(vf, rd, rn, FPZero, right_shift);
9193 break;
9194 case NEON_FCVTZU_imm:
9195 fcvtu(vf, rd, rn, FPZero, right_shift);
9196 break;
9197 case NEON_SSHLL:
9198 vf = vf_l;
9199 if (instr->Mask(NEON_Q)) {
9200 sshll2(vf, rd, rn, left_shift);
9201 } else {
9202 sshll(vf, rd, rn, left_shift);
9203 }
9204 break;
9205 case NEON_USHLL:
9206 vf = vf_l;
9207 if (instr->Mask(NEON_Q)) {
9208 ushll2(vf, rd, rn, left_shift);
9209 } else {
9210 ushll(vf, rd, rn, left_shift);
9211 }
9212 break;
9213 case NEON_SHRN:
9214 if (instr->Mask(NEON_Q)) {
9215 shrn2(vf, rd, rn, right_shift);
9216 } else {
9217 shrn(vf, rd, rn, right_shift);
9218 }
9219 break;
9220 case NEON_RSHRN:
9221 if (instr->Mask(NEON_Q)) {
9222 rshrn2(vf, rd, rn, right_shift);
9223 } else {
9224 rshrn(vf, rd, rn, right_shift);
9225 }
9226 break;
9227 case NEON_UQSHRN:
9228 if (instr->Mask(NEON_Q)) {
9229 uqshrn2(vf, rd, rn, right_shift);
9230 } else {
9231 uqshrn(vf, rd, rn, right_shift);
9232 }
9233 break;
9234 case NEON_UQRSHRN:
9235 if (instr->Mask(NEON_Q)) {
9236 uqrshrn2(vf, rd, rn, right_shift);
9237 } else {
9238 uqrshrn(vf, rd, rn, right_shift);
9239 }
9240 break;
9241 case NEON_SQSHRN:
9242 if (instr->Mask(NEON_Q)) {
9243 sqshrn2(vf, rd, rn, right_shift);
9244 } else {
9245 sqshrn(vf, rd, rn, right_shift);
9246 }
9247 break;
9248 case NEON_SQRSHRN:
9249 if (instr->Mask(NEON_Q)) {
9250 sqrshrn2(vf, rd, rn, right_shift);
9251 } else {
9252 sqrshrn(vf, rd, rn, right_shift);
9253 }
9254 break;
9255 case NEON_SQSHRUN:
9256 if (instr->Mask(NEON_Q)) {
9257 sqshrun2(vf, rd, rn, right_shift);
9258 } else {
9259 sqshrun(vf, rd, rn, right_shift);
9260 }
9261 break;
9262 case NEON_SQRSHRUN:
9263 if (instr->Mask(NEON_Q)) {
9264 sqrshrun2(vf, rd, rn, right_shift);
9265 } else {
9266 sqrshrun(vf, rd, rn, right_shift);
9267 }
9268 break;
9269 default:
9270 VIXL_UNIMPLEMENTED();
9271 }
9272}
9273
9274
9275void Simulator::VisitNEONTable(const Instruction* instr) {
9276 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9277 VectorFormat vf = nfd.GetVectorFormat();
9278
9279 SimVRegister& rd = ReadVRegister(instr->GetRd());
9280 SimVRegister& rn = ReadVRegister(instr->GetRn());
9281 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9282 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9283 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9284 SimVRegister& rm = ReadVRegister(instr->GetRm());
9285
9286 switch (instr->Mask(NEONTableMask)) {
9287 case NEON_TBL_1v:
9288 tbl(vf, rd, rn, rm);
9289 break;
9290 case NEON_TBL_2v:
9291 tbl(vf, rd, rn, rn2, rm);
9292 break;
9293 case NEON_TBL_3v:
9294 tbl(vf, rd, rn, rn2, rn3, rm);
9295 break;
9296 case NEON_TBL_4v:
9297 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9298 break;
9299 case NEON_TBX_1v:
9300 tbx(vf, rd, rn, rm);
9301 break;
9302 case NEON_TBX_2v:
9303 tbx(vf, rd, rn, rn2, rm);
9304 break;
9305 case NEON_TBX_3v:
9306 tbx(vf, rd, rn, rn2, rn3, rm);
9307 break;
9308 case NEON_TBX_4v:
9309 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9310 break;
9311 default:
9312 VIXL_UNIMPLEMENTED();
9313 }
9314}
9315
9316
9317void Simulator::VisitNEONPerm(const Instruction* instr) {
9318 NEONFormatDecoder nfd(instr);
9319 VectorFormat vf = nfd.GetVectorFormat();
9320
9321 SimVRegister& rd = ReadVRegister(instr->GetRd());
9322 SimVRegister& rn = ReadVRegister(instr->GetRn());
9323 SimVRegister& rm = ReadVRegister(instr->GetRm());
9324
9325 switch (instr->Mask(NEONPermMask)) {
9326 case NEON_TRN1:
9327 trn1(vf, rd, rn, rm);
9328 break;
9329 case NEON_TRN2:
9330 trn2(vf, rd, rn, rm);
9331 break;
9332 case NEON_UZP1:
9333 uzp1(vf, rd, rn, rm);
9334 break;
9335 case NEON_UZP2:
9336 uzp2(vf, rd, rn, rm);
9337 break;
9338 case NEON_ZIP1:
9339 zip1(vf, rd, rn, rm);
9340 break;
9341 case NEON_ZIP2:
9342 zip2(vf, rd, rn, rm);
9343 break;
9344 default:
9345 VIXL_UNIMPLEMENTED();
9346 }
9347}
9348
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009349void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00009350 SimVRegister& zd = ReadVRegister(instr->GetRd());
9351 SimVRegister& zn = ReadVRegister(instr->GetRn());
9352 SimVRegister& zm = ReadVRegister(instr->GetRm());
9353 SimVRegister temp;
9354
9355 VectorFormat vform = kFormatVnD;
9356 mov(vform, temp, zm);
9357
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009358 switch (instr->Mask(SVEAddressGenerationMask)) {
9359 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009360 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009361 break;
9362 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009363 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009364 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00009365 case ADR_z_az_s_same_scaled:
9366 vform = kFormatVnS;
9367 break;
9368 case ADR_z_az_d_same_scaled:
9369 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009370 break;
9371 default:
9372 VIXL_UNIMPLEMENTED();
9373 break;
9374 }
Martyn Capewell48522f52020-03-16 15:31:19 +00009375
9376 int shift_amount = instr->ExtractBits(11, 10);
9377 shl(vform, temp, temp, shift_amount);
9378 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009379}
9380
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009381void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9382 const Instruction* instr) {
9383 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07009384 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009385 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009386 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07009387 case ORR_z_zi: {
9388 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9389 uint64_t imm = instr->GetSVEImmLogical();
9390 // Valid immediate is a non-zero bits
9391 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009392 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9393 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07009394 SVEFormatFromLaneSizeInBytesLog2(lane_size),
9395 ReadVRegister(instr->GetRd()),
9396 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009397 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07009398 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009399 default:
9400 VIXL_UNIMPLEMENTED();
9401 break;
9402 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009403}
9404
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009405void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9406 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9407 case DUPM_z_i: {
9408 /* DUPM uses the same lane size and immediate encoding as bitwise logical
9409 * immediate instructions. */
9410 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9411 uint64_t imm = instr->GetSVEImmLogical();
9412 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9413 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9414 break;
9415 }
9416 default:
9417 VIXL_UNIMPLEMENTED();
9418 break;
9419 }
9420}
9421
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009422void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07009423 SimVRegister& zd = ReadVRegister(instr->GetRd());
9424 SimVRegister& zn = ReadVRegister(instr->GetRn());
9425 SimVRegister& zm = ReadVRegister(instr->GetRm());
9426 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9427
TatWai Chong13634762019-07-16 16:20:45 -07009428 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07009429 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009430 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009431 logical_op = AND;
9432 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009433 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009434 logical_op = BIC;
9435 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009436 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009437 logical_op = EOR;
9438 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07009439 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009440 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009441 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009442 default:
TatWai Chong13634762019-07-16 16:20:45 -07009443 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009444 VIXL_UNIMPLEMENTED();
9445 break;
9446 }
TatWai Chong13634762019-07-16 16:20:45 -07009447 // Lane size of registers is irrelevant to the bitwise operations, so perform
9448 // the operation on D-sized lanes.
9449 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009450}
9451
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009452void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00009453 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9454 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9455
9456 SimVRegister scratch;
9457 SimVRegister result;
9458
9459 bool for_division = false;
9460 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009461 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009462 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009463 shift_op = ASR;
9464 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009465 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009466 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009467 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009468 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009469 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009470 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009471 break;
9472 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009473 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009474 break;
9475 default:
9476 VIXL_UNIMPLEMENTED();
9477 break;
9478 }
Martyn Capewell83e86612020-02-19 15:46:15 +00009479
9480 std::pair<int, int> shift_and_lane_size =
9481 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9482 unsigned lane_size = shift_and_lane_size.second;
9483 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9484 int shift_dist = shift_and_lane_size.first;
9485
9486 if ((shift_op == ASR) && for_division) {
9487 asrd(vform, result, zdn, shift_dist);
9488 } else {
9489 if (shift_op == LSL) {
9490 // Shift distance is computed differently for LSL. Convert the result.
9491 shift_dist = (8 << lane_size) - shift_dist;
9492 }
9493 dup_immediate(vform, scratch, shift_dist);
9494 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9495 }
9496 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009497}
9498
9499void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9500 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009501 VectorFormat vform = instr->GetSVEVectorFormat();
9502 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9503 SimVRegister& zm = ReadVRegister(instr->GetRn());
9504 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell76c094a2020-02-13 17:26:49 +00009505 SimVRegister result;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009506
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009507 // SVE uses the whole (saturated) lane for the shift amount.
9508 bool shift_in_ls_byte = false;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009509
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009510 switch (form_hash_) {
9511 case Hash("asrr_z_p_zz"):
9512 sshr(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009513 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009514 case Hash("asr_z_p_zz"):
9515 sshr(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009516 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009517 case Hash("lslr_z_p_zz"):
9518 sshl(vform, result, zm, zdn, shift_in_ls_byte);
9519 break;
9520 case Hash("lsl_z_p_zz"):
9521 sshl(vform, result, zdn, zm, shift_in_ls_byte);
9522 break;
9523 case Hash("lsrr_z_p_zz"):
9524 ushr(vform, result, zm, zdn);
9525 break;
9526 case Hash("lsr_z_p_zz"):
9527 ushr(vform, result, zdn, zm);
9528 break;
9529 case Hash("sqrshl_z_p_zz"):
9530 sshl(vform, result, zdn, zm, shift_in_ls_byte)
9531 .Round(vform)
9532 .SignedSaturate(vform);
9533 break;
9534 case Hash("sqrshlr_z_p_zz"):
9535 sshl(vform, result, zm, zdn, shift_in_ls_byte)
9536 .Round(vform)
9537 .SignedSaturate(vform);
9538 break;
9539 case Hash("sqshl_z_p_zz"):
9540 sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
9541 break;
9542 case Hash("sqshlr_z_p_zz"):
9543 sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
9544 break;
9545 case Hash("srshl_z_p_zz"):
9546 sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9547 break;
9548 case Hash("srshlr_z_p_zz"):
9549 sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9550 break;
9551 case Hash("uqrshl_z_p_zz"):
9552 ushl(vform, result, zdn, zm, shift_in_ls_byte)
9553 .Round(vform)
9554 .UnsignedSaturate(vform);
9555 break;
9556 case Hash("uqrshlr_z_p_zz"):
9557 ushl(vform, result, zm, zdn, shift_in_ls_byte)
9558 .Round(vform)
9559 .UnsignedSaturate(vform);
9560 break;
9561 case Hash("uqshl_z_p_zz"):
9562 ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
9563 break;
9564 case Hash("uqshlr_z_p_zz"):
9565 ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
9566 break;
9567 case Hash("urshl_z_p_zz"):
9568 ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9569 break;
9570 case Hash("urshlr_z_p_zz"):
9571 ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009572 break;
9573 default:
9574 VIXL_UNIMPLEMENTED();
9575 break;
9576 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009577 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009578}
9579
9580void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9581 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009582 VectorFormat vform = instr->GetSVEVectorFormat();
9583 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9584 SimVRegister& zm = ReadVRegister(instr->GetRn());
9585 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9586
9587 SimVRegister result;
9588 Shift shift_op = ASR;
9589
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009590 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9591 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009592 break;
9593 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009594 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009595 break;
9596 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009597 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009598 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009599 default:
9600 VIXL_UNIMPLEMENTED();
9601 break;
9602 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009603 SVEBitwiseShiftHelper(shift_op,
9604 vform,
9605 result,
9606 zdn,
9607 zm,
9608 /* is_wide_elements = */ true);
9609 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009610}
9611
9612void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08009613 SimVRegister& zd = ReadVRegister(instr->GetRd());
9614 SimVRegister& zn = ReadVRegister(instr->GetRn());
9615
9616 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009617 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9618 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009619 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009620 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009621 break;
9622 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009623 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009624 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009625 break;
9626 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08009627 case LSR_z_zw:
9628 shift_op = LSR;
9629 break;
9630 default:
9631 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009632 VIXL_UNIMPLEMENTED();
9633 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08009634 }
9635
9636 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9637 case ASR_z_zi:
9638 case LSL_z_zi:
9639 case LSR_z_zi: {
9640 SimVRegister scratch;
9641 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00009642 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08009643 unsigned lane_size = shift_and_lane_size.second;
9644 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9645 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00009646 int shift_dist = shift_and_lane_size.first;
9647 if (shift_op == LSL) {
9648 // Shift distance is computed differently for LSL. Convert the result.
9649 shift_dist = (8 << lane_size) - shift_dist;
9650 }
9651 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08009652 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9653 break;
9654 }
9655 case ASR_z_zw:
9656 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009657 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009658 SVEBitwiseShiftHelper(shift_op,
9659 instr->GetSVEVectorFormat(),
9660 zd,
9661 zn,
9662 ReadVRegister(instr->GetRm()),
9663 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009664 break;
9665 default:
9666 VIXL_UNIMPLEMENTED();
9667 break;
9668 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009669}
9670
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009671void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00009672 // Although the instructions have a separate encoding class, the lane size is
9673 // encoded in the same way as most other SVE instructions.
9674 VectorFormat vform = instr->GetSVEVectorFormat();
9675
9676 int pattern = instr->GetImmSVEPredicateConstraint();
9677 int count = GetPredicateConstraintLaneCount(vform, pattern);
9678 int multiplier = instr->ExtractBits(19, 16) + 1;
9679
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009680 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009681 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009682 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009683 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009684 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009685 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009686 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009687 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009688 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009689 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009690 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009691 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009692 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009693 default:
9694 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00009695 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009696 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00009697
9698 WriteXRegister(instr->GetRd(),
9699 IncDecN(ReadXRegister(instr->GetRd()),
9700 count * multiplier,
9701 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009702}
9703
9704void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009705 VectorFormat vform = instr->GetSVEVectorFormat();
9706 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9707 VIXL_UNIMPLEMENTED();
9708 }
9709
9710 int pattern = instr->GetImmSVEPredicateConstraint();
9711 int count = GetPredicateConstraintLaneCount(vform, pattern);
9712 int multiplier = instr->ExtractBits(19, 16) + 1;
9713
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009714 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9715 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009716 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009717 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009718 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009719 break;
9720 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009721 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009722 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009723 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009724 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009725 default:
9726 VIXL_UNIMPLEMENTED();
9727 break;
9728 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009729
9730 SimVRegister& zd = ReadVRegister(instr->GetRd());
9731 SimVRegister scratch;
9732 dup_immediate(vform,
9733 scratch,
9734 IncDecN(0,
9735 count * multiplier,
9736 LaneSizeInBitsFromFormat(vform)));
9737 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009738}
9739
9740void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9741 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009742 // Although the instructions have a separate encoding class, the lane size is
9743 // encoded in the same way as most other SVE instructions.
9744 VectorFormat vform = instr->GetSVEVectorFormat();
9745
9746 int pattern = instr->GetImmSVEPredicateConstraint();
9747 int count = GetPredicateConstraintLaneCount(vform, pattern);
9748 int multiplier = instr->ExtractBits(19, 16) + 1;
9749
9750 unsigned width = kXRegSize;
9751 bool is_signed = false;
9752
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009753 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009754 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009755 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009756 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009757 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009758 width = kWRegSize;
9759 VIXL_FALLTHROUGH();
9760 case SQDECB_r_rs_x:
9761 case SQDECD_r_rs_x:
9762 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009763 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009764 is_signed = true;
9765 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009766 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009767 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009768 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009769 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009770 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009771 width = kWRegSize;
9772 VIXL_FALLTHROUGH();
9773 case SQINCB_r_rs_x:
9774 case SQINCD_r_rs_x:
9775 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009776 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009777 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009778 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009779 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009780 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009781 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009782 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009783 width = kWRegSize;
9784 VIXL_FALLTHROUGH();
9785 case UQDECB_r_rs_x:
9786 case UQDECD_r_rs_x:
9787 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009788 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009789 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009790 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009791 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009792 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009793 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009794 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009795 width = kWRegSize;
9796 VIXL_FALLTHROUGH();
9797 case UQINCB_r_rs_x:
9798 case UQINCD_r_rs_x:
9799 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009800 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009801 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009802 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009803 default:
9804 VIXL_UNIMPLEMENTED();
9805 break;
9806 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009807
9808 WriteXRegister(instr->GetRd(),
9809 IncDecN(ReadXRegister(instr->GetRd()),
9810 count * multiplier,
9811 width,
9812 true,
9813 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009814}
9815
9816void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9817 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009818 VectorFormat vform = instr->GetSVEVectorFormat();
9819 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9820 VIXL_UNIMPLEMENTED();
9821 }
9822
9823 int pattern = instr->GetImmSVEPredicateConstraint();
9824 int count = GetPredicateConstraintLaneCount(vform, pattern);
9825 int multiplier = instr->ExtractBits(19, 16) + 1;
9826
9827 SimVRegister& zd = ReadVRegister(instr->GetRd());
9828 SimVRegister scratch;
9829 dup_immediate(vform,
9830 scratch,
9831 IncDecN(0,
9832 count * multiplier,
9833 LaneSizeInBitsFromFormat(vform)));
9834
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009835 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9836 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009837 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009838 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009839 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009840 break;
9841 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009842 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009843 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009844 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009845 break;
9846 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009847 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009848 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009849 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009850 break;
9851 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009852 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009853 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009854 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009855 break;
9856 default:
9857 VIXL_UNIMPLEMENTED();
9858 break;
9859 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009860}
9861
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009862void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009863 switch (instr->Mask(SVEElementCountMask)) {
9864 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009865 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009866 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009867 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00009868 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009869 break;
9870 default:
9871 VIXL_UNIMPLEMENTED();
9872 break;
9873 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00009874
9875 // Although the instructions are separated, the lane size is encoded in the
9876 // same way as most other SVE instructions.
9877 VectorFormat vform = instr->GetSVEVectorFormat();
9878
9879 int pattern = instr->GetImmSVEPredicateConstraint();
9880 int count = GetPredicateConstraintLaneCount(vform, pattern);
9881 int multiplier = instr->ExtractBits(19, 16) + 1;
9882 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009883}
9884
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009885void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009886 VectorFormat vform = instr->GetSVEVectorFormat();
9887 SimVRegister& vdn = ReadVRegister(instr->GetRd());
9888 SimVRegister& zm = ReadVRegister(instr->GetRn());
9889 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9890
Martyn Capewell310a0822020-09-08 20:09:17 +01009891 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9892
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009893 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9894 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009895 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009896 break;
9897 default:
9898 VIXL_UNIMPLEMENTED();
9899 break;
9900 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009901}
9902
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009903void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07009904 VectorFormat vform = instr->GetSVEVectorFormat();
9905 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9906 SimVRegister& zm = ReadVRegister(instr->GetRn());
9907 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9908
Martyn Capewell310a0822020-09-08 20:09:17 +01009909 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
TatWai Chongd316c5e2019-10-16 12:22:10 -07009910
Martyn Capewell310a0822020-09-08 20:09:17 +01009911 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009912 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009913 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009914 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009915 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009916 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009917 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009918 break;
9919 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009920 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009921 break;
9922 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009923 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009924 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009925 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009926 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009927 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009928 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009929 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009930 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009931 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009932 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009933 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009934 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009935 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009936 break;
9937 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009938 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009939 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009940 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009941 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009942 break;
9943 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009944 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009945 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009946 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009947 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009948 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009949 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009950 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009951 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009952 default:
9953 VIXL_UNIMPLEMENTED();
9954 break;
9955 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07009956 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009957}
9958
9959void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9960 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00009961 VectorFormat vform = instr->GetSVEVectorFormat();
9962 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9963 VIXL_UNIMPLEMENTED();
9964 }
9965
9966 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9967 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9968 SimVRegister result;
9969
9970 int i1 = instr->ExtractBit(5);
9971 SimVRegister add_sub_imm, min_max_imm, mul_imm;
9972 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9973 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9974 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9975 dup_immediate(vform, add_sub_imm, i1 ? one : half);
9976 dup_immediate(vform, min_max_imm, i1 ? one : 0);
9977 dup_immediate(vform, mul_imm, i1 ? two : half);
9978
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009979 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9980 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009981 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009982 break;
9983 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009984 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009985 break;
9986 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009987 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009988 break;
9989 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009990 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009991 break;
9992 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009993 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009994 break;
9995 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009996 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009997 break;
9998 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009999 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010000 break;
10001 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +000010002 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010003 break;
10004 default:
10005 VIXL_UNIMPLEMENTED();
10006 break;
10007 }
Martyn Capewella2fadc22020-01-16 16:09:55 +000010008 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010009}
10010
10011void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +000010012 VectorFormat vform = instr->GetSVEVectorFormat();
10013 SimVRegister& zd = ReadVRegister(instr->GetRd());
10014 SimVRegister& zm = ReadVRegister(instr->GetRn());
10015
Martyn Capewell310a0822020-09-08 20:09:17 +010010016 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10017
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010018 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010019 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +000010020 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010021 break;
10022 default:
10023 VIXL_UNIMPLEMENTED();
10024 break;
10025 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010026}
10027
10028void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -070010029 VectorFormat vform = instr->GetSVEVectorFormat();
10030 SimVRegister& zd = ReadVRegister(instr->GetRd());
10031 SimVRegister& zn = ReadVRegister(instr->GetRn());
10032 SimVRegister& zm = ReadVRegister(instr->GetRm());
10033
Martyn Capewell310a0822020-09-08 20:09:17 +010010034 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10035
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010036 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
10037 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -070010038 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010039 break;
10040 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -070010041 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010042 break;
10043 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010044 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010045 break;
10046 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010047 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010048 break;
10049 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -070010050 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010051 break;
10052 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010053 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010054 break;
10055 default:
10056 VIXL_UNIMPLEMENTED();
10057 break;
10058 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010059}
10060
10061void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -080010062 SimPRegister& pd = ReadPRegister(instr->GetPd());
10063 SimVRegister& zn = ReadVRegister(instr->GetRn());
10064 SimVRegister& zm = ReadVRegister(instr->GetRm());
10065 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10066 VectorFormat vform = instr->GetSVEVectorFormat();
10067 SimVRegister result;
10068
Martyn Capewell310a0822020-09-08 20:09:17 +010010069 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10070
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010071 switch (instr->Mask(SVEFPCompareVectorsMask)) {
10072 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010073 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010074 break;
10075 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010076 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010077 break;
10078 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010079 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010080 break;
10081 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010082 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010083 break;
10084 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010085 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010086 break;
10087 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010088 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010089 break;
10090 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010091 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010092 break;
10093 default:
10094 VIXL_UNIMPLEMENTED();
10095 break;
10096 }
TatWai Chong47c26842020-02-10 01:51:32 -080010097
10098 ExtractFromSimVRegister(vform, pd, result);
10099 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010100}
10101
10102void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -080010103 SimPRegister& pd = ReadPRegister(instr->GetPd());
10104 SimVRegister& zn = ReadVRegister(instr->GetRn());
10105 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10106 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chonge3775132020-02-16 22:13:17 -080010107
Martyn Capewell310a0822020-09-08 20:09:17 +010010108 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10109
10110 SimVRegister result;
TatWai Chonge3775132020-02-16 22:13:17 -080010111 SimVRegister zeros;
10112 dup_immediate(kFormatVnD, zeros, 0);
10113
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010114 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10115 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010116 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010117 break;
10118 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010119 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010120 break;
10121 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010122 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010123 break;
10124 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010125 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010126 break;
10127 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010128 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010129 break;
10130 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010131 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010132 break;
10133 default:
10134 VIXL_UNIMPLEMENTED();
10135 break;
10136 }
TatWai Chonge3775132020-02-16 22:13:17 -080010137
10138 ExtractFromSimVRegister(vform, pd, result);
10139 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010140}
10141
10142void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010143 VectorFormat vform = instr->GetSVEVectorFormat();
10144
10145 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10146 VIXL_UNIMPLEMENTED();
10147 }
10148
10149 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10150 SimVRegister& zm = ReadVRegister(instr->GetRn());
10151 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10152 int rot = instr->ExtractBit(16);
10153
10154 SimVRegister result;
10155
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010156 switch (instr->Mask(SVEFPComplexAdditionMask)) {
10157 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010158 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010159 break;
10160 default:
10161 VIXL_UNIMPLEMENTED();
10162 break;
10163 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010164 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010165}
10166
10167void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +010010168 VectorFormat vform = instr->GetSVEVectorFormat();
10169
10170 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10171 VIXL_UNIMPLEMENTED();
10172 }
10173
10174 SimVRegister& zda = ReadVRegister(instr->GetRd());
10175 SimVRegister& zn = ReadVRegister(instr->GetRn());
10176 SimVRegister& zm = ReadVRegister(instr->GetRm());
10177 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10178 int rot = instr->ExtractBits(14, 13);
10179
10180 SimVRegister result;
10181
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010182 switch (instr->Mask(SVEFPComplexMulAddMask)) {
10183 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +010010184 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010185 break;
10186 default:
10187 VIXL_UNIMPLEMENTED();
10188 break;
10189 }
Martyn Capewell75f1c432020-03-30 09:23:27 +010010190 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010191}
10192
10193void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +010010194 SimVRegister& zda = ReadVRegister(instr->GetRd());
10195 SimVRegister& zn = ReadVRegister(instr->GetRn());
10196 int rot = instr->ExtractBits(11, 10);
10197 unsigned zm_code = instr->GetRm();
10198 int index = -1;
10199 VectorFormat vform, vform_dup;
10200
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010201 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10202 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010203 vform = kFormatVnH;
10204 vform_dup = kFormatVnS;
10205 index = zm_code >> 3;
10206 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010207 break;
10208 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010209 vform = kFormatVnS;
10210 vform_dup = kFormatVnD;
10211 index = zm_code >> 4;
10212 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010213 break;
10214 default:
10215 VIXL_UNIMPLEMENTED();
10216 break;
10217 }
Martyn Capewelle4886e52020-03-30 09:28:52 +010010218
10219 if (index >= 0) {
10220 SimVRegister temp;
10221 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10222 fcmla(vform, zda, zn, temp, zda, rot);
10223 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010224}
10225
Martyn Capewell894962f2020-02-05 15:46:44 +000010226typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10227 LogicVRegister dst,
10228 const LogicVRegister& src);
10229
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010230void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +000010231 VectorFormat vform = instr->GetSVEVectorFormat();
10232 SimVRegister& vd = ReadVRegister(instr->GetRd());
10233 SimVRegister& zn = ReadVRegister(instr->GetRn());
10234 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10235 int lane_size = LaneSizeInBitsFromFormat(vform);
10236
10237 uint64_t inactive_value = 0;
10238 FastReduceFn fn = nullptr;
10239
Martyn Capewell310a0822020-09-08 20:09:17 +010010240 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10241
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010242 switch (instr->Mask(SVEFPFastReductionMask)) {
10243 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010244 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010245 break;
10246 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010247 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10248 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010249 break;
10250 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010251 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10252 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010253 break;
10254 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010255 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10256 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010257 break;
10258 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010259 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10260 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010261 break;
10262 default:
10263 VIXL_UNIMPLEMENTED();
10264 break;
10265 }
Martyn Capewell894962f2020-02-05 15:46:44 +000010266
10267 SimVRegister scratch;
10268 dup_immediate(vform, scratch, inactive_value);
10269 mov_merging(vform, scratch, pg, zn);
10270 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010271}
10272
10273void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +000010274 VectorFormat vform = kFormatUndefined;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010275
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010276 switch (instr->Mask(SVEFPMulIndexMask)) {
10277 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010278 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010279 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010280 case FMUL_z_zzi_h_i3h:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010281 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010282 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010283 break;
10284 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010285 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010286 break;
10287 default:
10288 VIXL_UNIMPLEMENTED();
10289 break;
10290 }
Martyn Capewell50e9f552020-01-07 17:45:03 +000010291
10292 SimVRegister& zd = ReadVRegister(instr->GetRd());
10293 SimVRegister& zn = ReadVRegister(instr->GetRn());
10294 SimVRegister temp;
10295
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010296 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
Martyn Capewell50e9f552020-01-07 17:45:03 +000010297 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010298}
10299
10300void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -080010301 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongf8d29f12020-02-16 22:53:18 -080010302 SimVRegister& zd = ReadVRegister(instr->GetRd());
10303 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10304 SimVRegister result;
10305
Martyn Capewell310a0822020-09-08 20:09:17 +010010306 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10307
TatWai Chongf8d29f12020-02-16 22:53:18 -080010308 if (instr->ExtractBit(15) == 0) {
10309 // Floating-point multiply-accumulate writing addend.
10310 SimVRegister& zm = ReadVRegister(instr->GetRm());
10311 SimVRegister& zn = ReadVRegister(instr->GetRn());
10312
10313 switch (instr->Mask(SVEFPMulAddMask)) {
10314 // zda = zda + zn * zm
10315 case FMLA_z_p_zzz:
10316 fmla(vform, result, zd, zn, zm);
10317 break;
10318 // zda = -zda + -zn * zm
10319 case FNMLA_z_p_zzz:
10320 fneg(vform, result, zd);
10321 fmls(vform, result, result, zn, zm);
10322 break;
10323 // zda = zda + -zn * zm
10324 case FMLS_z_p_zzz:
10325 fmls(vform, result, zd, zn, zm);
10326 break;
10327 // zda = -zda + zn * zm
10328 case FNMLS_z_p_zzz:
10329 fneg(vform, result, zd);
10330 fmla(vform, result, result, zn, zm);
10331 break;
10332 default:
10333 VIXL_UNIMPLEMENTED();
10334 break;
10335 }
10336 } else {
10337 // Floating-point multiply-accumulate writing multiplicand.
10338 SimVRegister& za = ReadVRegister(instr->GetRm());
10339 SimVRegister& zm = ReadVRegister(instr->GetRn());
10340
10341 switch (instr->Mask(SVEFPMulAddMask)) {
10342 // zdn = za + zdn * zm
10343 case FMAD_z_p_zzz:
10344 fmla(vform, result, za, zd, zm);
10345 break;
10346 // zdn = -za + -zdn * zm
10347 case FNMAD_z_p_zzz:
10348 fneg(vform, result, za);
10349 fmls(vform, result, result, zd, zm);
10350 break;
10351 // zdn = za + -zdn * zm
10352 case FMSB_z_p_zzz:
10353 fmls(vform, result, za, zd, zm);
10354 break;
10355 // zdn = -za + zdn * zm
10356 case FNMSB_z_p_zzz:
10357 fneg(vform, result, za);
10358 fmla(vform, result, result, zd, zm);
10359 break;
10360 default:
10361 VIXL_UNIMPLEMENTED();
10362 break;
10363 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010364 }
TatWai Chongf8d29f12020-02-16 22:53:18 -080010365
10366 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010367}
10368
10369void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010370 VectorFormat vform = kFormatUndefined;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010371
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010372 switch (instr->Mask(SVEFPMulAddIndexMask)) {
10373 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010374 case FMLS_z_zzzi_d:
10375 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010376 break;
10377 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010378 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010379 vform = kFormatVnS;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010380 break;
10381 case FMLA_z_zzzi_h:
10382 case FMLS_z_zzzi_h:
10383 case FMLA_z_zzzi_h_i3h:
10384 case FMLS_z_zzzi_h_i3h:
10385 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010386 break;
10387 default:
10388 VIXL_UNIMPLEMENTED();
10389 break;
10390 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010391
10392 SimVRegister& zd = ReadVRegister(instr->GetRd());
10393 SimVRegister& zn = ReadVRegister(instr->GetRn());
10394 SimVRegister temp;
10395
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010396 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010397 if (instr->ExtractBit(10) == 1) {
10398 fmls(vform, zd, zd, zn, temp);
10399 } else {
10400 fmla(vform, zd, zd, zn, temp);
10401 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010402}
10403
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010404void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -080010405 SimVRegister& zd = ReadVRegister(instr->GetRd());
10406 SimVRegister& zn = ReadVRegister(instr->GetRn());
10407 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10408 int dst_data_size;
10409 int src_data_size;
10410
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010411 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010412 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010413 case FCVTZU_z_p_z_d2w:
10414 dst_data_size = kSRegSize;
10415 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010416 break;
10417 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010418 case FCVTZU_z_p_z_d2x:
10419 dst_data_size = kDRegSize;
10420 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010421 break;
10422 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010423 case FCVTZU_z_p_z_fp162h:
10424 dst_data_size = kHRegSize;
10425 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010426 break;
10427 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010428 case FCVTZU_z_p_z_fp162w:
10429 dst_data_size = kSRegSize;
10430 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010431 break;
10432 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010433 case FCVTZU_z_p_z_fp162x:
10434 dst_data_size = kDRegSize;
10435 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010436 break;
10437 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010438 case FCVTZU_z_p_z_s2w:
10439 dst_data_size = kSRegSize;
10440 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010441 break;
10442 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010443 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010444 dst_data_size = kDRegSize;
10445 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010446 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010447 default:
10448 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -080010449 dst_data_size = 0;
10450 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010451 break;
10452 }
TatWai Chongdb7437c2020-01-09 17:44:10 -080010453
10454 VectorFormat vform =
10455 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -080010456
10457 if (instr->ExtractBit(16) == 0) {
10458 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10459 } else {
10460 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10461 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010462}
10463
10464void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -080010465 SimVRegister& zd = ReadVRegister(instr->GetRd());
10466 SimVRegister& zn = ReadVRegister(instr->GetRn());
10467 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10468 int dst_data_size;
10469 int src_data_size;
10470
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010471 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010472 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010473 dst_data_size = kHRegSize;
10474 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010475 break;
10476 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010477 dst_data_size = kSRegSize;
10478 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010479 break;
10480 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010481 dst_data_size = kDRegSize;
10482 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010483 break;
10484 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010485 dst_data_size = kSRegSize;
10486 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010487 break;
10488 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010489 dst_data_size = kDRegSize;
10490 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010491 break;
10492 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010493 dst_data_size = kHRegSize;
10494 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010495 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010496 default:
10497 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -080010498 dst_data_size = 0;
10499 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010500 break;
10501 }
TatWai Chong2cb1b612020-03-04 23:51:21 -080010502 VectorFormat vform =
10503 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10504
10505 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010506}
10507
10508void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010509 SimVRegister& zd = ReadVRegister(instr->GetRd());
10510 SimVRegister& zn = ReadVRegister(instr->GetRn());
10511 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10512 VectorFormat vform = instr->GetSVEVectorFormat();
10513 SimVRegister result;
10514
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010515 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010516 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010517 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010518 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010519 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -080010520 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010521 break;
10522 default:
10523 VIXL_UNIMPLEMENTED();
10524 break;
10525 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010526 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010527}
10528
10529void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010530 SimVRegister& zd = ReadVRegister(instr->GetRd());
10531 SimVRegister& zn = ReadVRegister(instr->GetRn());
10532 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10533 VectorFormat vform = instr->GetSVEVectorFormat();
10534 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10535 bool exact_exception = false;
10536
Martyn Capewell310a0822020-09-08 20:09:17 +010010537 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10538
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010539 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010540 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010541 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010542 break;
10543 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010544 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010545 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010546 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010547 break;
10548 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010549 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010550 break;
10551 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010552 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010553 break;
10554 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010555 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010556 break;
10557 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010558 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010559 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010560 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010561 VIXL_UNIMPLEMENTED();
10562 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010563 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010564
10565 SimVRegister result;
10566 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10567 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010568}
10569
10570void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -080010571 SimVRegister& zd = ReadVRegister(instr->GetRd());
10572 SimVRegister& zn = ReadVRegister(instr->GetRn());
10573 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10574 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10575 int dst_data_size;
10576 int src_data_size;
10577
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010578 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010579 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010580 case UCVTF_z_p_z_h2fp16:
10581 dst_data_size = kHRegSize;
10582 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010583 break;
10584 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010585 case UCVTF_z_p_z_w2d:
10586 dst_data_size = kDRegSize;
10587 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010588 break;
10589 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010590 case UCVTF_z_p_z_w2fp16:
10591 dst_data_size = kHRegSize;
10592 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010593 break;
10594 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010595 case UCVTF_z_p_z_w2s:
10596 dst_data_size = kSRegSize;
10597 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010598 break;
10599 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010600 case UCVTF_z_p_z_x2d:
10601 dst_data_size = kDRegSize;
10602 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010603 break;
10604 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010605 case UCVTF_z_p_z_x2fp16:
10606 dst_data_size = kHRegSize;
10607 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010608 break;
10609 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010610 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010611 dst_data_size = kSRegSize;
10612 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010613 break;
10614 default:
10615 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -080010616 dst_data_size = 0;
10617 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010618 break;
10619 }
TatWai Chong31cd6a02020-01-10 13:03:26 -080010620
10621 VectorFormat vform =
10622 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10623
10624 if (instr->ExtractBit(16) == 0) {
10625 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10626 } else {
10627 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10628 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010629}
10630
10631void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +000010632 VectorFormat vform = instr->GetSVEVectorFormat();
10633 SimVRegister& zd = ReadVRegister(instr->GetRd());
10634 SimVRegister& zn = ReadVRegister(instr->GetRn());
10635 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10636
Martyn Capewell310a0822020-09-08 20:09:17 +010010637 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10638
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010639 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10640 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010641 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010642 break;
10643 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010644 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010645 break;
10646 default:
10647 VIXL_UNIMPLEMENTED();
10648 break;
10649 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010650}
10651
10652void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010653 VectorFormat vform = instr->GetSVEVectorFormat();
10654 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10655
10656 int count = CountActiveLanes(vform, pg);
10657
10658 if (instr->ExtractBit(11) == 0) {
10659 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10660 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10661 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010662 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010663 break;
10664 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010665 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010666 break;
10667 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010668 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010669 break;
10670 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010671 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010672 break;
10673 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010674 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010675 break;
10676 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010677 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010678 break;
10679 default:
10680 VIXL_UNIMPLEMENTED();
10681 break;
10682 }
10683 } else {
10684 bool is_saturating = (instr->ExtractBit(18) == 0);
10685 bool decrement =
10686 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10687 bool is_signed = (instr->ExtractBit(16) == 0);
10688 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10689 unsigned width = sf ? kXRegSize : kWRegSize;
10690
10691 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10692 case DECP_r_p_r:
10693 case INCP_r_p_r:
10694 case SQDECP_r_p_r_sx:
10695 case SQDECP_r_p_r_x:
10696 case SQINCP_r_p_r_sx:
10697 case SQINCP_r_p_r_x:
10698 case UQDECP_r_p_r_uw:
10699 case UQDECP_r_p_r_x:
10700 case UQINCP_r_p_r_uw:
10701 case UQINCP_r_p_r_x:
10702 WriteXRegister(instr->GetRd(),
10703 IncDecN(ReadXRegister(instr->GetRd()),
10704 decrement ? -count : count,
10705 width,
10706 is_saturating,
10707 is_signed));
10708 break;
10709 default:
10710 VIXL_UNIMPLEMENTED();
10711 break;
10712 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010713 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010714}
10715
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010716uint64_t Simulator::IncDecN(uint64_t acc,
10717 int64_t delta,
10718 unsigned n,
10719 bool is_saturating,
10720 bool is_signed) {
10721 VIXL_ASSERT(n <= 64);
10722 VIXL_ASSERT(IsIntN(n, delta));
10723
10724 uint64_t sign_mask = UINT64_C(1) << (n - 1);
10725 uint64_t mask = GetUintMask(n);
10726
10727 acc &= mask; // Ignore initial accumulator high bits.
10728 uint64_t result = (acc + delta) & mask;
10729
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010730 bool result_negative = ((result & sign_mask) != 0);
10731
10732 if (is_saturating) {
10733 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +000010734 bool acc_negative = ((acc & sign_mask) != 0);
10735 bool delta_negative = delta < 0;
10736
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010737 // If the signs of the operands are the same, but different from the
10738 // result, there was an overflow.
10739 if ((acc_negative == delta_negative) &&
10740 (acc_negative != result_negative)) {
10741 if (result_negative) {
10742 // Saturate to [..., INT<n>_MAX].
10743 result_negative = false;
10744 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
10745 } else {
10746 // Saturate to [INT<n>_MIN, ...].
10747 result_negative = true;
10748 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
10749 }
10750 }
10751 } else {
10752 if ((delta < 0) && (result > acc)) {
10753 // Saturate to [0, ...].
10754 result = 0;
10755 } else if ((delta > 0) && (result < acc)) {
10756 // Saturate to [..., UINT<n>_MAX].
10757 result = mask;
10758 }
10759 }
10760 }
10761
10762 // Sign-extend if necessary.
10763 if (result_negative && is_signed) result |= ~mask;
10764
10765 return result;
10766}
10767
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010768void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010769 VectorFormat vform = instr->GetSVEVectorFormat();
10770 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010771 switch (instr->Mask(SVEIndexGenerationMask)) {
10772 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010773 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010774 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010775 case INDEX_z_rr: {
10776 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10777 : instr->ExtractSignedBits(9, 5);
10778 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10779 : instr->ExtractSignedBits(20, 16);
10780 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010781 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010782 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010783 default:
10784 VIXL_UNIMPLEMENTED();
10785 break;
10786 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010787}
10788
10789void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -070010790 VectorFormat vform = instr->GetSVEVectorFormat();
10791 SimVRegister& zd = ReadVRegister(instr->GetRd());
10792 SimVRegister& zn = ReadVRegister(instr->GetRn());
10793 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010794 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10795 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010796 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010797 break;
10798 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010799 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010800 break;
10801 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010802 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010803 break;
10804 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010805 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010806 break;
10807 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010808 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010809 break;
10810 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010811 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010812 break;
10813 default:
10814 VIXL_UNIMPLEMENTED();
10815 break;
10816 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010817}
10818
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010819void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010820 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -070010821 VectorFormat vform = instr->GetSVEVectorFormat();
10822 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10823 SimVRegister& zm = ReadVRegister(instr->GetRn());
10824 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10825 SimVRegister result;
10826
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010827 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010828 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010829 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010830 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010831 case SUBR_z_p_zz:
10832 sub(vform, result, zm, zdn);
10833 break;
10834 case SUB_z_p_zz:
10835 sub(vform, result, zdn, zm);
10836 break;
10837 default:
10838 VIXL_UNIMPLEMENTED();
10839 break;
10840 }
10841 mov_merging(vform, zdn, pg, result);
10842}
10843
10844void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10845 VectorFormat vform = instr->GetSVEVectorFormat();
10846 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10847 SimVRegister& zm = ReadVRegister(instr->GetRn());
10848 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10849 SimVRegister result;
10850
10851 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010852 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010853 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010854 break;
10855 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010856 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010857 break;
10858 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010859 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010860 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010861 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010862 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010863 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010864 default:
10865 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010866 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010867 }
10868 mov_merging(vform, zdn, pg, result);
10869}
10870
10871void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10872 VectorFormat vform = instr->GetSVEVectorFormat();
10873 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10874 SimVRegister& zm = ReadVRegister(instr->GetRn());
10875 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10876 SimVRegister result;
10877
10878 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10879 case MUL_z_p_zz:
10880 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010881 break;
10882 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010883 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010884 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010885 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010886 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010887 break;
10888 default:
10889 VIXL_UNIMPLEMENTED();
10890 break;
10891 }
TatWai Chong13634762019-07-16 16:20:45 -070010892 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010893}
10894
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010895void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10896 const Instruction* instr) {
10897 VectorFormat vform = instr->GetSVEVectorFormat();
10898 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10899 SimVRegister& zm = ReadVRegister(instr->GetRn());
10900 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10901 SimVRegister result;
10902
10903 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10904 case SABD_z_p_zz:
10905 absdiff(vform, result, zdn, zm, true);
10906 break;
10907 case SMAX_z_p_zz:
10908 smax(vform, result, zdn, zm);
10909 break;
10910 case SMIN_z_p_zz:
10911 smin(vform, result, zdn, zm);
10912 break;
10913 case UABD_z_p_zz:
10914 absdiff(vform, result, zdn, zm, false);
10915 break;
10916 case UMAX_z_p_zz:
10917 umax(vform, result, zdn, zm);
10918 break;
10919 case UMIN_z_p_zz:
10920 umin(vform, result, zdn, zm);
10921 break;
10922 default:
10923 VIXL_UNIMPLEMENTED();
10924 break;
10925 }
10926 mov_merging(vform, zdn, pg, result);
10927}
10928
10929void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10930 VectorFormat vform = instr->GetSVEVectorFormat();
10931 SimVRegister& zd = ReadVRegister(instr->GetRd());
10932 SimVRegister scratch;
10933
10934 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10935 case MUL_z_zi:
10936 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10937 mul(vform, zd, zd, scratch);
10938 break;
10939 default:
10940 VIXL_UNIMPLEMENTED();
10941 break;
10942 }
10943}
10944
10945void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10946 VectorFormat vform = instr->GetSVEVectorFormat();
10947 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10948 SimVRegister& zm = ReadVRegister(instr->GetRn());
10949 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10950 SimVRegister result;
10951
10952 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10953
10954 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10955 case SDIVR_z_p_zz:
10956 sdiv(vform, result, zm, zdn);
10957 break;
10958 case SDIV_z_p_zz:
10959 sdiv(vform, result, zdn, zm);
10960 break;
10961 case UDIVR_z_p_zz:
10962 udiv(vform, result, zm, zdn);
10963 break;
10964 case UDIV_z_p_zz:
10965 udiv(vform, result, zdn, zm);
10966 break;
10967 default:
10968 VIXL_UNIMPLEMENTED();
10969 break;
10970 }
10971 mov_merging(vform, zdn, pg, result);
10972}
10973
10974void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10975 VectorFormat vform = instr->GetSVEVectorFormat();
10976 SimVRegister& zd = ReadVRegister(instr->GetRd());
10977 SimVRegister scratch;
10978
10979 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10980 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10981
10982 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10983 case SMAX_z_zi:
10984 dup_immediate(vform, scratch, signed_imm);
10985 smax(vform, zd, zd, scratch);
10986 break;
10987 case SMIN_z_zi:
10988 dup_immediate(vform, scratch, signed_imm);
10989 smin(vform, zd, zd, scratch);
10990 break;
10991 case UMAX_z_zi:
10992 dup_immediate(vform, scratch, unsigned_imm);
10993 umax(vform, zd, zd, scratch);
10994 break;
10995 case UMIN_z_zi:
10996 dup_immediate(vform, scratch, unsigned_imm);
10997 umin(vform, zd, zd, scratch);
10998 break;
10999 default:
11000 VIXL_UNIMPLEMENTED();
11001 break;
11002 }
11003}
11004
11005void Simulator::VisitSVEIntCompareScalarCountAndLimit(
11006 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -070011007 unsigned rn_code = instr->GetRn();
11008 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011009 SimPRegister& pd = ReadPRegister(instr->GetPd());
11010 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongc844bb22019-06-10 15:32:53 -070011011
Martyn Capewellf0844012020-10-23 16:38:26 +010011012 bool is_64_bit = instr->ExtractBit(12) == 1;
11013 int rsize = is_64_bit ? kXRegSize : kWRegSize;
11014 uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
11015
11016 uint64_t usrc1 = ReadXRegister(rn_code);
11017 int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11018 uint64_t usrc2 = ssrc2 & mask;
11019
11020 bool reverse = (form_hash_ == Hash("whilege_p_p_rr")) ||
11021 (form_hash_ == Hash("whilegt_p_p_rr")) ||
11022 (form_hash_ == Hash("whilehi_p_p_rr")) ||
11023 (form_hash_ == Hash("whilehs_p_p_rr"));
11024
11025 int lane_count = LaneCountFromFormat(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011026 bool last = true;
Martyn Capewellf0844012020-10-23 16:38:26 +010011027 for (int i = 0; i < lane_count; i++) {
11028 usrc1 &= mask;
11029 int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
11030
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011031 bool cond = false;
Martyn Capewellf0844012020-10-23 16:38:26 +010011032 switch (form_hash_) {
11033 case Hash("whilele_p_p_rr"):
11034 cond = ssrc1 <= ssrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070011035 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011036 case Hash("whilelo_p_p_rr"):
11037 cond = usrc1 < usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011038 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011039 case Hash("whilels_p_p_rr"):
11040 cond = usrc1 <= usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011041 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011042 case Hash("whilelt_p_p_rr"):
11043 cond = ssrc1 < ssrc2;
11044 break;
11045 case Hash("whilege_p_p_rr"):
11046 cond = ssrc1 >= ssrc2;
11047 break;
11048 case Hash("whilegt_p_p_rr"):
11049 cond = ssrc1 > ssrc2;
11050 break;
11051 case Hash("whilehi_p_p_rr"):
11052 cond = usrc1 > usrc2;
11053 break;
11054 case Hash("whilehs_p_p_rr"):
11055 cond = usrc1 >= usrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070011056 break;
11057 default:
TatWai Chongc844bb22019-06-10 15:32:53 -070011058 VIXL_UNIMPLEMENTED();
11059 break;
11060 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011061 last = last && cond;
11062 LogicPRegister dst(pd);
Martyn Capewellf0844012020-10-23 16:38:26 +010011063 int lane = reverse ? ((lane_count - 1) - i) : i;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011064 dst.SetActive(vform, lane, last);
Martyn Capewellf0844012020-10-23 16:38:26 +010011065 usrc1 += reverse ? -1 : 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011066 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011067
11068 PredTest(vform, GetPTrue(), pd);
11069 LogSystemRegister(NZCV);
11070}
11071
11072void Simulator::VisitSVEConditionallyTerminateScalars(
11073 const Instruction* instr) {
11074 unsigned rn_code = instr->GetRn();
11075 unsigned rm_code = instr->GetRm();
11076 bool is_64_bit = instr->ExtractBit(22) == 1;
11077 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
11078 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11079 bool term;
11080 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
11081 case CTERMEQ_rr:
11082 term = src1 == src2;
11083 break;
11084 case CTERMNE_rr:
11085 term = src1 != src2;
11086 break;
11087 default:
11088 term = false;
11089 VIXL_UNIMPLEMENTED();
11090 break;
11091 }
11092 ReadNzcv().SetN(term ? 1 : 0);
11093 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -070011094 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011095}
11096
11097void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011098 bool commute_inputs = false;
11099 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011100 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11101 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011102 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011103 break;
11104 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011105 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011106 break;
11107 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011108 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011109 break;
11110 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011111 cond = ge;
11112 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011113 break;
11114 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011115 cond = gt;
11116 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011117 break;
11118 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011119 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011120 break;
11121 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011122 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011123 VIXL_UNIMPLEMENTED();
11124 break;
11125 }
TatWai Chong302729c2019-06-14 16:18:51 -070011126
11127 VectorFormat vform = instr->GetSVEVectorFormat();
11128 SimVRegister src2;
11129 dup_immediate(vform,
11130 src2,
11131 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11132 SVEIntCompareVectorsHelper(cond,
11133 vform,
11134 ReadPRegister(instr->GetPd()),
11135 ReadPRegister(instr->GetPgLow8()),
11136 commute_inputs ? src2
11137 : ReadVRegister(instr->GetRn()),
11138 commute_inputs ? ReadVRegister(instr->GetRn())
11139 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011140}
11141
11142void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011143 bool commute_inputs = false;
11144 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011145 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11146 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011147 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011148 break;
11149 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011150 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011151 break;
11152 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011153 cond = hi;
11154 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011155 break;
11156 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011157 cond = hs;
11158 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011159 break;
11160 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011161 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011162 VIXL_UNIMPLEMENTED();
11163 break;
11164 }
TatWai Chong302729c2019-06-14 16:18:51 -070011165
11166 VectorFormat vform = instr->GetSVEVectorFormat();
11167 SimVRegister src2;
11168 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11169 SVEIntCompareVectorsHelper(cond,
11170 vform,
11171 ReadPRegister(instr->GetPd()),
11172 ReadPRegister(instr->GetPgLow8()),
11173 commute_inputs ? src2
11174 : ReadVRegister(instr->GetRn()),
11175 commute_inputs ? ReadVRegister(instr->GetRn())
11176 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011177}
11178
11179void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -070011180 Instr op = instr->Mask(SVEIntCompareVectorsMask);
11181 bool is_wide_elements = false;
11182 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011183 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -070011184 case CMPGE_p_p_zw:
11185 case CMPGT_p_p_zw:
11186 case CMPHI_p_p_zw:
11187 case CMPHS_p_p_zw:
11188 case CMPLE_p_p_zw:
11189 case CMPLO_p_p_zw:
11190 case CMPLS_p_p_zw:
11191 case CMPLT_p_p_zw:
11192 case CMPNE_p_p_zw:
11193 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011194 break;
TatWai Chong96713fe2019-06-04 16:39:37 -070011195 }
11196
TatWai Chong302729c2019-06-14 16:18:51 -070011197 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -070011198 switch (op) {
11199 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011200 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011201 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011202 break;
11203 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011204 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011205 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011206 break;
11207 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011208 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011209 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011210 break;
11211 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011212 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011213 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011214 break;
11215 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011216 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011217 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011218 break;
11219 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011220 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011221 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -070011222 break;
11223 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011224 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -070011225 break;
11226 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011227 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -070011228 break;
11229 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011230 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -070011231 break;
11232 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011233 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011234 break;
11235 default:
11236 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -070011237 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011238 break;
11239 }
TatWai Chong96713fe2019-06-04 16:39:37 -070011240
TatWai Chong302729c2019-06-14 16:18:51 -070011241 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -070011242 instr->GetSVEVectorFormat(),
11243 ReadPRegister(instr->GetPd()),
11244 ReadPRegister(instr->GetPgLow8()),
11245 ReadVRegister(instr->GetRn()),
11246 ReadVRegister(instr->GetRm()),
11247 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011248}
11249
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011250void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011251 VectorFormat vform = instr->GetSVEVectorFormat();
11252 SimVRegister& zd = ReadVRegister(instr->GetRd());
11253 SimVRegister& zn = ReadVRegister(instr->GetRn());
11254
11255 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11256 (vform == kFormatVnD));
11257
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011258 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011259 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +000011260 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011261 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011262 default:
11263 VIXL_UNIMPLEMENTED();
11264 break;
11265 }
11266}
11267
11268void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011269 VectorFormat vform = instr->GetSVEVectorFormat();
11270 SimVRegister& zd = ReadVRegister(instr->GetRd());
11271 SimVRegister& zn = ReadVRegister(instr->GetRn());
11272 SimVRegister& zm = ReadVRegister(instr->GetRm());
11273
11274 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11275 (vform == kFormatVnD));
11276
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011277 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011278 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +000011279 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011280 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011281 default:
11282 VIXL_UNIMPLEMENTED();
11283 break;
11284 }
11285}
11286
11287void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11288 const Instruction* instr) {
11289 SimVRegister& zd = ReadVRegister(instr->GetRd());
11290 SimVRegister& zn = ReadVRegister(instr->GetRn());
11291
11292 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011293 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011294 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11295 // Record the movprfx, so the next ExecuteInstruction() can check it.
11296 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011297 break;
11298 default:
11299 VIXL_UNIMPLEMENTED();
11300 break;
11301 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011302}
11303
11304void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +010011305 VectorFormat vform = instr->GetSVEVectorFormat();
11306
11307 SimVRegister& zd = ReadVRegister(instr->GetRd());
11308 SimVRegister& zm = ReadVRegister(instr->GetRm());
11309
11310 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011311 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011312 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011313 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011314 break;
11315 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011316 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011317 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011318 case MAD_z_p_zzz:
11319 // 'za' is encoded in 'Rn'.
11320 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011321 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011322 case MSB_z_p_zzz: {
11323 // 'za' is encoded in 'Rn'.
11324 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11325 break;
11326 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011327 default:
11328 VIXL_UNIMPLEMENTED();
11329 break;
11330 }
Jacob Bramley22023df2019-05-14 17:55:43 +010011331 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011332}
11333
11334void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011335 VectorFormat vform = instr->GetSVEVectorFormat();
11336 SimVRegister& zda = ReadVRegister(instr->GetRd());
11337 SimVRegister& zn = ReadVRegister(instr->GetRn());
11338 SimVRegister& zm = ReadVRegister(instr->GetRm());
11339
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011340 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
11341 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011342 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011343 break;
11344 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011345 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011346 break;
11347 default:
11348 VIXL_UNIMPLEMENTED();
11349 break;
11350 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011351}
11352
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011353void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011354 VectorFormat vform = instr->GetSVEVectorFormat();
11355 SimVRegister& zn = ReadVRegister(instr->GetRn());
11356 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11357 SimVRegister& zd = ReadVRegister(instr->GetRd());
11358
11359 switch (instr->Mask(SVEMovprfxMask)) {
11360 case MOVPRFX_z_p_z:
11361 if (instr->ExtractBit(16)) {
11362 mov_merging(vform, zd, pg, zn);
11363 } else {
11364 mov_zeroing(vform, zd, pg, zn);
11365 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011366
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011367 // Record the movprfx, so the next ExecuteInstruction() can check it.
11368 movprfx_ = instr;
11369 break;
11370 default:
11371 VIXL_UNIMPLEMENTED();
11372 break;
11373 }
11374}
11375
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011376void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011377 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +010011378 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011379 SimVRegister& zn = ReadVRegister(instr->GetRn());
11380 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11381
11382 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11383 switch (instr->Mask(SVEIntReductionLogicalMask)) {
11384 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011385 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011386 break;
11387 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011388 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011389 break;
11390 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011391 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011392 break;
11393 default:
11394 VIXL_UNIMPLEMENTED();
11395 break;
11396 }
11397 } else {
11398 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011399 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011400 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011401 break;
11402 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011403 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011404 break;
11405 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011406 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011407 break;
11408 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011409 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011410 break;
11411 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011412 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011413 break;
11414 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011415 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011416 break;
11417 default:
11418 VIXL_UNIMPLEMENTED();
11419 break;
11420 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011421 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011422}
11423
11424void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011425 VectorFormat vform = instr->GetSVEVectorFormat();
11426 SimVRegister& zn = ReadVRegister(instr->GetRn());
11427
11428 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011429 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11430 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011431 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011432 break;
11433 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011434 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011435 break;
11436 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011437 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011438 break;
11439 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011440 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011441 break;
11442 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011443 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011444 break;
11445 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011446 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011447 break;
11448 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011449 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011450 break;
11451 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011452 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011453 break;
11454 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011455 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011456 break;
11457 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011458 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011459 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011460 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011461 break;
11462 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011463 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011464 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011465 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011466 break;
11467 default:
11468 VIXL_UNIMPLEMENTED();
11469 break;
11470 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011471
11472 SimVRegister& zd = ReadVRegister(instr->GetRd());
11473 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11474 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011475}
11476
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011477void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011478 // There is only one instruction in this group.
11479 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11480
11481 VectorFormat vform = instr->GetSVEVectorFormat();
11482 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11483 SimVRegister& zd = ReadVRegister(instr->GetRd());
11484
Martyn Capewell310a0822020-09-08 20:09:17 +010011485 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11486
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011487 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011488 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011489 case FCPY_z_p_i: {
11490 int imm8 = instr->ExtractBits(12, 5);
11491 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11492 Instruction::Imm8ToFP64(imm8));
11493 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011494 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011495 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011496 default:
11497 VIXL_UNIMPLEMENTED();
11498 break;
11499 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011500 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011501}
11502
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011503void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11504 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +010011505 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010011506 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +010011507 SimVRegister scratch;
11508
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011509 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11510 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011511
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011512 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011513 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011514 add_uint(vform, zd, zd, imm);
11515 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011516 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011517 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11518 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011519 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011520 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11521 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011522 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011523 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +010011524 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011525 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011526 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011527 sub_uint(vform, zd, zd, imm);
11528 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011529 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011530 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11531 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011532 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011533 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11534 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011535 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011536 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011537 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011538}
TatWai Chong6995bfd2019-09-26 10:48:05 +010011539
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011540void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11541 SimVRegister& zd = ReadVRegister(instr->GetRd());
11542
Martyn Capewell8ed83522020-08-11 16:19:43 +010011543 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011544 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +010011545 int shift = instr->ExtractBit(13) * 8;
11546 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011547
11548 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11549 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +010011550 // The encoding of byte-sized lanes with lsl #8 is undefined.
11551 if ((format == kFormatVnB) && (shift == 8)) {
11552 VIXL_UNIMPLEMENTED();
11553 } else {
11554 dup_immediate(format, zd, imm);
11555 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011556 break;
11557 default:
11558 VIXL_UNIMPLEMENTED();
11559 break;
11560 }
11561}
11562
11563void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11564 VectorFormat vform = instr->GetSVEVectorFormat();
11565 SimVRegister& zd = ReadVRegister(instr->GetRd());
11566
11567 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011568 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +010011569 switch (vform) {
11570 case kFormatVnH:
11571 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11572 break;
11573 case kFormatVnS:
11574 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11575 break;
11576 case kFormatVnD:
11577 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11578 break;
11579 default:
11580 VIXL_UNIMPLEMENTED();
11581 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011582 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011583 default:
11584 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011585 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011586 }
11587}
11588
11589void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11590 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011591 switch (instr->Mask(
11592 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11593 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011594 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011595 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011596 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011597 break;
11598 default:
11599 VIXL_UNIMPLEMENTED();
11600 break;
11601 }
TatWai Chong113d9192020-05-19 01:02:36 -070011602
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011603 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11604 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011605}
11606
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011607void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011608 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011609 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11610 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011611 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011612 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011613 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011614 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011615 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011616 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011617 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011618 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011619 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011620 break;
11621 default:
11622 VIXL_UNIMPLEMENTED();
11623 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011624 }
TatWai Chong113d9192020-05-19 01:02:36 -070011625
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011626 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11627 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011628}
11629
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011630void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11631 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011632 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11633 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011634 VIXL_UNIMPLEMENTED();
11635 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011636 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011637 VIXL_UNIMPLEMENTED();
11638 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011639 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011640 VIXL_UNIMPLEMENTED();
11641 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011642 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011643 VIXL_UNIMPLEMENTED();
11644 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011645 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011646 VIXL_UNIMPLEMENTED();
11647 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011648 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011649 VIXL_UNIMPLEMENTED();
11650 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011651 case LDFF1H_z_p_ai_s:
11652 VIXL_UNIMPLEMENTED();
11653 break;
11654 case LDFF1SB_z_p_ai_s:
11655 VIXL_UNIMPLEMENTED();
11656 break;
11657 case LDFF1SH_z_p_ai_s:
11658 VIXL_UNIMPLEMENTED();
11659 break;
11660 case LDFF1W_z_p_ai_s:
11661 VIXL_UNIMPLEMENTED();
11662 break;
11663 default:
11664 VIXL_UNIMPLEMENTED();
11665 break;
11666 }
11667}
11668
11669void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11670 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011671 switch (
11672 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11673 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011674 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011675 break;
11676 default:
11677 VIXL_UNIMPLEMENTED();
11678 break;
11679 }
TatWai Chong113d9192020-05-19 01:02:36 -070011680
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011681 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11682 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011683}
11684
11685void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11686 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011687 switch (
11688 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011689 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011690 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011691 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011692 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011693 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011694 break;
11695 default:
11696 VIXL_UNIMPLEMENTED();
11697 break;
11698 }
11699}
11700
11701void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11702 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011703 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011704 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011705 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011706 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011707 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011708 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011709 break;
11710 default:
11711 VIXL_UNIMPLEMENTED();
11712 break;
11713 }
11714}
11715
11716void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11717 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011718 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011719 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011720 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011721 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011722 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011723 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011724 break;
11725 default:
11726 VIXL_UNIMPLEMENTED();
11727 break;
11728 }
11729}
11730
11731void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11732 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011733 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011734 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011735 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011736 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011737 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011738 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +010011739 if (instr->GetRm() == kZeroRegCode) {
11740 VIXL_UNIMPLEMENTED();
11741 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011742 break;
11743 default:
11744 VIXL_UNIMPLEMENTED();
11745 break;
11746 }
11747}
11748
11749void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -070011750 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011751 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011752 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -070011753 case LD1RB_z_p_bi_u16:
11754 case LD1RB_z_p_bi_u32:
11755 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011756 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011757 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011758 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -070011759 case LD1RW_z_p_bi_u32:
11760 case LD1RW_z_p_bi_u64:
11761 case LD1RD_z_p_bi_u64:
11762 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011763 break;
11764 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011765 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011766 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011767 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011768 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011769 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -070011770 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011771 break;
11772 default:
TatWai Chong85e15102020-05-04 21:00:40 -070011773 // This encoding group is complete, so no other values should be possible.
11774 VIXL_UNREACHABLE();
11775 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011776 break;
11777 }
TatWai Chong85e15102020-05-04 21:00:40 -070011778
11779 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11780 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11781 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11782 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11783 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11784 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11785 VectorFormat unpack_vform =
11786 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11787 SimVRegister temp;
11788 ld1r(vform, unpack_vform, temp, base, is_signed);
11789 mov_zeroing(vform,
11790 ReadVRegister(instr->GetRt()),
11791 ReadPRegister(instr->GetPgLow8()),
11792 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011793}
11794
11795void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11796 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11797 case LDR_p_bi: {
11798 SimPRegister& pt = ReadPRegister(instr->GetPt());
11799 int pl = GetPredicateLengthInBytes();
11800 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11801 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11802 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11803 for (int i = 0; i < pl; i++) {
11804 pt.Insert(i, Memory::Read<uint8_t>(address + i));
11805 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011806 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011807 break;
11808 }
11809 default:
11810 VIXL_UNIMPLEMENTED();
11811 break;
11812 }
11813}
11814
11815void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011816 switch (instr->Mask(SVELoadVectorRegisterMask)) {
11817 case LDR_z_bi: {
11818 SimVRegister& zt = ReadVRegister(instr->GetRt());
11819 int vl = GetVectorLengthInBytes();
11820 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11821 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11822 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11823 for (int i = 0; i < vl; i++) {
11824 zt.Insert(i, Memory::Read<uint8_t>(address + i));
11825 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011826 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011827 break;
11828 }
11829 default:
11830 VIXL_UNIMPLEMENTED();
11831 break;
11832 }
11833}
11834
11835void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11836 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011837 switch (instr->Mask(
11838 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011839 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011840 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011841 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011842 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011843 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011844 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011845 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011846 case LDFF1D_z_p_bz_d_x32_scaled:
11847 case LDFF1SH_z_p_bz_d_x32_scaled:
11848 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011849 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011850 default:
11851 VIXL_UNIMPLEMENTED();
11852 break;
11853 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011854
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011855 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11856 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011857}
11858
11859void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11860 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011861 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11862 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011863 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011864 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011865 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011866 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011867 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011868 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011869 case LDFF1D_z_p_bz_d_64_scaled:
11870 case LDFF1SH_z_p_bz_d_64_scaled:
11871 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011872 break;
11873 default:
11874 VIXL_UNIMPLEMENTED();
11875 break;
11876 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011877
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011878 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011879}
11880
11881void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11882 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011883 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11884 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011885 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011886 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011887 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011888 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011889 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011890 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011891 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011892 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011893 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011894 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011895 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011896 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011897 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011898 break;
11899 default:
11900 VIXL_UNIMPLEMENTED();
11901 break;
11902 }
TatWai Chong113d9192020-05-19 01:02:36 -070011903
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011904 SVEGatherLoadScalarPlusVectorHelper(instr,
11905 kFormatVnD,
11906 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011907}
11908
11909void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11910 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011911 switch (instr->Mask(
11912 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11913 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011914 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011915 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011916 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011917 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011918 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011919 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011920 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011921 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011922 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011923 case LDFF1D_z_p_bz_d_x32_unscaled:
11924 case LDFF1SB_z_p_bz_d_x32_unscaled:
11925 case LDFF1SH_z_p_bz_d_x32_unscaled:
11926 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011927 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011928 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011929 VIXL_UNIMPLEMENTED();
11930 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011931 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011932
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011933 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11934 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011935}
11936
11937void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11938 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011939 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11940 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011941 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011942 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011943 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011944 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011945 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011946 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011947 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011948 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011949 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011950 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011951 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011952 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011953 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011954 break;
11955 default:
11956 VIXL_UNIMPLEMENTED();
11957 break;
11958 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +000011959 bool is_signed = instr->ExtractBit(14) == 0;
11960 bool is_ff = instr->ExtractBit(13) == 1;
11961 // Note that these instructions don't use the Dtype encoding.
11962 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11963 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11964 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11965 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11966 if (is_ff) {
11967 VIXL_UNIMPLEMENTED();
11968 } else {
11969 SVEStructuredLoadHelper(kFormatVnD,
11970 ReadPRegister(instr->GetPgLow8()),
11971 instr->GetRt(),
11972 addr,
11973 is_signed);
11974 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011975}
11976
11977void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11978 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011979 switch (
11980 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011981 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011982 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011983 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011984 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011985 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011986 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011987 default:
11988 VIXL_UNIMPLEMENTED();
11989 break;
11990 }
11991}
11992
11993void Simulator::
11994 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
11995 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011996 switch (instr->Mask(
11997 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011998 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011999 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012000 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012001 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012002 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012003 break;
12004 default:
12005 VIXL_UNIMPLEMENTED();
12006 break;
12007 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012008}
12009
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012010void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
12011 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012012 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070012013 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012014 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012015 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012016 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012017 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012018 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012019 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012020 VIXL_UNIMPLEMENTED();
12021 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012022 }
12023}
12024
12025void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
12026 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +000012027 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +000012028 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012029 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012030 case LDFF1B_z_p_br_u16:
12031 case LDFF1B_z_p_br_u32:
12032 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012033 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012034 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012035 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012036 case LDFF1W_z_p_br_u32:
12037 case LDFF1W_z_p_br_u64:
12038 case LDFF1D_z_p_br_u64:
12039 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012040 break;
12041 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012042 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012043 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012044 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012045 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012046 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012047 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012048 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012049 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012050 // This encoding group is complete, so no other values should be possible.
12051 VIXL_UNREACHABLE();
12052 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012053 break;
12054 }
Jacob Bramley85a9c102019-12-09 17:48:29 +000012055
12056 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12057 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12058 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12059 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12060 uint64_t offset = ReadXRegister(instr->GetRm());
12061 offset <<= msize_in_bytes_log2;
12062 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12063 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12064 SVEFaultTolerantLoadHelper(vform,
12065 ReadPRegister(instr->GetPgLow8()),
12066 instr->GetRt(),
12067 addr,
12068 kSVEFirstFaultLoad,
12069 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012070}
12071
12072void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
12073 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012074 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012075 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012076 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012077 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012078 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012079 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012080 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012081 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012082 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012083 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012084 case LDNF1W_z_p_bi_u32:
12085 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012086 break;
12087 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012088 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012089 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012090 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012091 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012092 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012093 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012094 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012095 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012096 VIXL_UNIMPLEMENTED();
12097 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012098 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012099 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12100 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12101 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12102 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12103 int vl = GetVectorLengthInBytes();
12104 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12105 uint64_t offset =
12106 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12107 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12108 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12109 SVEFaultTolerantLoadHelper(vform,
12110 ReadPRegister(instr->GetPgLow8()),
12111 instr->GetRt(),
12112 addr,
12113 kSVENonFaultLoad,
12114 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012115}
12116
12117void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12118 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012119 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12120 VectorFormat vform = kFormatUndefined;
12121
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012122 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12123 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012124 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012125 break;
12126 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012127 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012128 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012129 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012130 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012131 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012132 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012133 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012134 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012135 default:
12136 VIXL_UNIMPLEMENTED();
12137 break;
12138 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012139 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12140 int vl = GetVectorLengthInBytes();
12141 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12142 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12143 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12144 SVEStructuredLoadHelper(vform,
12145 pg,
12146 instr->GetRt(),
12147 addr,
12148 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012149}
12150
12151void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12152 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012153 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12154 VectorFormat vform = kFormatUndefined;
12155
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012156 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12157 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012158 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012159 break;
12160 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012161 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012162 break;
12163 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012164 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012165 break;
12166 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012167 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012168 break;
12169 default:
12170 VIXL_UNIMPLEMENTED();
12171 break;
12172 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012173 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12174 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12175 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12176 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12177 SVEStructuredLoadHelper(vform,
12178 pg,
12179 instr->GetRt(),
12180 addr,
12181 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012182}
12183
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012184void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
12185 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012186 SimVRegister& zt = ReadVRegister(instr->GetRt());
12187 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12188
12189 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12190 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
12191
12192 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012193 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
12194 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012195 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012196 break;
12197 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012198 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012199 break;
12200 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012201 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012202 break;
12203 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012204 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012205 break;
12206 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012207 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012208 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012209 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012210 ld1(kFormat16B, zt, addr + offset);
12211 mov_zeroing(vform, zt, pg, zt);
12212 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012213}
12214
12215void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
12216 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012217 SimVRegister& zt = ReadVRegister(instr->GetRt());
12218 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12219
12220 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12221 uint64_t offset = ReadXRegister(instr->GetRm());
12222
12223 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012224 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
12225 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012226 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012227 break;
12228 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012229 vform = kFormatVnD;
12230 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012231 break;
12232 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012233 vform = kFormatVnH;
12234 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012235 break;
12236 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012237 vform = kFormatVnS;
12238 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012239 break;
12240 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012241 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012242 break;
12243 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012244 ld1(kFormat16B, zt, addr + offset);
12245 mov_zeroing(vform, zt, pg, zt);
12246 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012247}
12248
12249void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12250 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012251 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12252 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012253 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012254 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012255 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012256 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012257 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012258 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012259 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012260 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012261 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012262 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012263 case LD4W_z_p_bi_contiguous: {
12264 int vl = GetVectorLengthInBytes();
12265 int msz = instr->ExtractBits(24, 23);
12266 int reg_count = instr->ExtractBits(22, 21) + 1;
12267 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12268 LogicSVEAddressVector addr(
12269 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12270 addr.SetMsizeInBytesLog2(msz);
12271 addr.SetRegCount(reg_count);
12272 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12273 ReadPRegister(instr->GetPgLow8()),
12274 instr->GetRt(),
12275 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012276 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012277 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012278 default:
12279 VIXL_UNIMPLEMENTED();
12280 break;
12281 }
12282}
12283
12284void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12285 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012286 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12287 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012288 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012289 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012290 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012291 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012292 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012293 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012294 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012295 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012296 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012297 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000012298 case LD4W_z_p_br_contiguous: {
12299 int msz = instr->ExtractBits(24, 23);
12300 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12301 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12302 LogicSVEAddressVector addr(
12303 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12304 addr.SetMsizeInBytesLog2(msz);
12305 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12306 SVEStructuredLoadHelper(vform,
12307 ReadPRegister(instr->GetPgLow8()),
12308 instr->GetRt(),
12309 addr,
12310 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012311 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000012312 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012313 default:
12314 VIXL_UNIMPLEMENTED();
12315 break;
12316 }
12317}
12318
12319void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12320 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012321 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12322 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012323 case ST1W_z_p_bz_s_x32_scaled: {
12324 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12325 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12326 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12327 uint64_t base = ReadXRegister(instr->GetRn());
12328 SVEOffsetModifier mod =
12329 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12330 LogicSVEAddressVector addr(base,
12331 &ReadVRegister(instr->GetRm()),
12332 kFormatVnS,
12333 mod,
12334 scale);
12335 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12336 SVEStructuredStoreHelper(kFormatVnS,
12337 ReadPRegister(instr->GetPgLow8()),
12338 instr->GetRt(),
12339 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012340 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012341 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012342 default:
12343 VIXL_UNIMPLEMENTED();
12344 break;
12345 }
12346}
12347
12348void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12349 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012350 switch (
12351 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12352 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012353 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012354 case ST1W_z_p_bz_s_x32_unscaled: {
12355 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12356 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12357 uint64_t base = ReadXRegister(instr->GetRn());
12358 SVEOffsetModifier mod =
12359 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12360 LogicSVEAddressVector addr(base,
12361 &ReadVRegister(instr->GetRm()),
12362 kFormatVnS,
12363 mod);
12364 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12365 SVEStructuredStoreHelper(kFormatVnS,
12366 ReadPRegister(instr->GetPgLow8()),
12367 instr->GetRt(),
12368 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012369 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012370 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012371 default:
12372 VIXL_UNIMPLEMENTED();
12373 break;
12374 }
12375}
12376
12377void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12378 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012379 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012380 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12381 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012382 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012383 break;
12384 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012385 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012386 break;
12387 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012388 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012389 break;
12390 default:
12391 VIXL_UNIMPLEMENTED();
12392 break;
12393 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012394 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12395 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12396 addr.SetMsizeInBytesLog2(msz);
12397 SVEStructuredStoreHelper(kFormatVnS,
12398 ReadPRegister(instr->GetPgLow8()),
12399 instr->GetRt(),
12400 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012401}
12402
12403void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12404 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012405 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12406 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012407 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012408 case ST1W_z_p_bz_d_64_scaled: {
12409 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12410 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12411 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12412 uint64_t base = ReadXRegister(instr->GetRn());
12413 LogicSVEAddressVector addr(base,
12414 &ReadVRegister(instr->GetRm()),
12415 kFormatVnD,
12416 SVE_LSL,
12417 scale);
12418 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12419 SVEStructuredStoreHelper(kFormatVnD,
12420 ReadPRegister(instr->GetPgLow8()),
12421 instr->GetRt(),
12422 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012423 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012424 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012425 default:
12426 VIXL_UNIMPLEMENTED();
12427 break;
12428 }
12429}
12430
12431void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12432 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012433 switch (
12434 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12435 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012436 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012437 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012438 case ST1W_z_p_bz_d_64_unscaled: {
12439 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12440 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012441 uint64_t base = ReadXRegister(instr->GetRn());
12442 LogicSVEAddressVector addr(base,
12443 &ReadVRegister(instr->GetRm()),
12444 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070012445 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012446 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12447 SVEStructuredStoreHelper(kFormatVnD,
12448 ReadPRegister(instr->GetPgLow8()),
12449 instr->GetRt(),
12450 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012451 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012452 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012453 default:
12454 VIXL_UNIMPLEMENTED();
12455 break;
12456 }
12457}
12458
12459void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12460 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012461 switch (instr->Mask(
12462 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12463 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012464 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012465 case ST1W_z_p_bz_d_x32_scaled: {
12466 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12467 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12468 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12469 uint64_t base = ReadXRegister(instr->GetRn());
12470 SVEOffsetModifier mod =
12471 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12472 LogicSVEAddressVector addr(base,
12473 &ReadVRegister(instr->GetRm()),
12474 kFormatVnD,
12475 mod,
12476 scale);
12477 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12478 SVEStructuredStoreHelper(kFormatVnD,
12479 ReadPRegister(instr->GetPgLow8()),
12480 instr->GetRt(),
12481 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012482 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012483 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012484 default:
12485 VIXL_UNIMPLEMENTED();
12486 break;
12487 }
12488}
12489
12490void Simulator::
12491 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12492 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012493 switch (instr->Mask(
12494 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12495 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012496 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012497 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012498 case ST1W_z_p_bz_d_x32_unscaled: {
12499 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12500 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12501 uint64_t base = ReadXRegister(instr->GetRn());
12502 SVEOffsetModifier mod =
12503 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12504 LogicSVEAddressVector addr(base,
12505 &ReadVRegister(instr->GetRm()),
12506 kFormatVnD,
12507 mod);
12508 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12509 SVEStructuredStoreHelper(kFormatVnD,
12510 ReadPRegister(instr->GetPgLow8()),
12511 instr->GetRt(),
12512 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012513 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012514 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012515 default:
12516 VIXL_UNIMPLEMENTED();
12517 break;
12518 }
12519}
12520
12521void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12522 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012523 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012524 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12525 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012526 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012527 break;
12528 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012529 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012530 break;
12531 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012532 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012533 break;
12534 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012535 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012536 break;
12537 default:
12538 VIXL_UNIMPLEMENTED();
12539 break;
12540 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012541 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12542 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12543 addr.SetMsizeInBytesLog2(msz);
12544 SVEStructuredStoreHelper(kFormatVnD,
12545 ReadPRegister(instr->GetPgLow8()),
12546 instr->GetRt(),
12547 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012548}
12549
12550void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12551 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012552 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12553 VectorFormat vform = kFormatUndefined;
12554
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012555 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12556 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012557 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012558 break;
12559 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012560 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012561 break;
12562 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012563 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012564 break;
12565 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012566 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012567 break;
12568 default:
12569 VIXL_UNIMPLEMENTED();
12570 break;
12571 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012572 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12573 int vl = GetVectorLengthInBytes();
12574 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12575 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12576 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12577 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012578}
12579
12580void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12581 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012582 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12583 VectorFormat vform = kFormatUndefined;
12584
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012585 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12586 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012587 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012588 break;
12589 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012590 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012591 break;
12592 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012593 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012594 break;
12595 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012596 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012597 break;
12598 default:
12599 VIXL_UNIMPLEMENTED();
12600 break;
12601 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012602 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12603 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12604 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12605 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12606 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012607}
12608
12609void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12610 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012611 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12612 case ST1B_z_p_bi:
12613 case ST1D_z_p_bi:
12614 case ST1H_z_p_bi:
12615 case ST1W_z_p_bi: {
12616 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012617 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12618 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12619 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12620 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12621 uint64_t offset =
12622 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012623 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012624 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012625 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012626 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12627 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012628 ReadPRegister(instr->GetPgLow8()),
12629 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012630 addr);
12631 break;
12632 }
12633 default:
12634 VIXL_UNIMPLEMENTED();
12635 break;
12636 }
12637}
12638
12639void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12640 const Instruction* instr) {
12641 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12642 case ST1B_z_p_br:
12643 case ST1D_z_p_br:
12644 case ST1H_z_p_br:
12645 case ST1W_z_p_br: {
12646 uint64_t offset = ReadXRegister(instr->GetRm());
12647 offset <<= instr->ExtractBits(24, 23);
12648 VectorFormat vform =
12649 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12650 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012651 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12652 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012653 ReadPRegister(instr->GetPgLow8()),
12654 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012655 addr);
12656 break;
12657 }
12658 default:
12659 VIXL_UNIMPLEMENTED();
12660 break;
12661 }
12662}
12663
12664void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12665 const Instruction* instr) {
12666 VectorFormat vform = instr->GetSVEVectorFormat();
12667 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12668 SimVRegister z_result;
12669
12670 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12671 case CPY_z_p_v:
12672 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12673 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12674 break;
12675 default:
12676 VIXL_UNIMPLEMENTED();
12677 break;
12678 }
12679}
12680
12681void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12682 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012683 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12684 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012685 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012686 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012687 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012688 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012689 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012690 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012691 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012692 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012693 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012694 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012695 case ST4W_z_p_bi_contiguous: {
12696 int vl = GetVectorLengthInBytes();
12697 int msz = instr->ExtractBits(24, 23);
12698 int reg_count = instr->ExtractBits(22, 21) + 1;
12699 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12700 LogicSVEAddressVector addr(
12701 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12702 addr.SetMsizeInBytesLog2(msz);
12703 addr.SetRegCount(reg_count);
12704 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12705 ReadPRegister(instr->GetPgLow8()),
12706 instr->GetRt(),
12707 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012708 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012709 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012710 default:
12711 VIXL_UNIMPLEMENTED();
12712 break;
12713 }
12714}
12715
12716void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12717 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012718 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12719 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012720 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012721 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012722 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012723 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012724 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012725 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012726 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012727 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012728 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012729 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012730 case ST4W_z_p_br_contiguous: {
12731 int msz = instr->ExtractBits(24, 23);
12732 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12733 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12734 LogicSVEAddressVector addr(
12735 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12736 addr.SetMsizeInBytesLog2(msz);
12737 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12738 SVEStructuredStoreHelper(vform,
12739 ReadPRegister(instr->GetPgLow8()),
12740 instr->GetRt(),
12741 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012742 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012743 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012744 default:
12745 VIXL_UNIMPLEMENTED();
12746 break;
12747 }
12748}
12749
12750void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12751 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12752 case STR_p_bi: {
12753 SimPRegister& pt = ReadPRegister(instr->GetPt());
12754 int pl = GetPredicateLengthInBytes();
12755 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12756 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12757 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12758 for (int i = 0; i < pl; i++) {
12759 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
12760 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012761 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012762 break;
12763 }
12764 default:
12765 VIXL_UNIMPLEMENTED();
12766 break;
12767 }
12768}
12769
12770void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12771 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12772 case STR_z_bi: {
12773 SimVRegister& zt = ReadVRegister(instr->GetRt());
12774 int vl = GetVectorLengthInBytes();
12775 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12776 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12777 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12778 for (int i = 0; i < vl; i++) {
12779 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
12780 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012781 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012782 break;
12783 }
12784 default:
12785 VIXL_UNIMPLEMENTED();
12786 break;
12787 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012788}
12789
12790void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012791 VectorFormat vform = instr->GetSVEVectorFormat();
12792 SimVRegister& zda = ReadVRegister(instr->GetRd());
12793 SimVRegister& zn = ReadVRegister(instr->GetRn());
12794
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012795 switch (instr->Mask(SVEMulIndexMask)) {
12796 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012797 sdot(vform,
12798 zda,
12799 zn,
12800 ReadVRegister(instr->ExtractBits(19, 16)),
12801 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012802 break;
12803 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012804 sdot(vform,
12805 zda,
12806 zn,
12807 ReadVRegister(instr->ExtractBits(18, 16)),
12808 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012809 break;
12810 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012811 udot(vform,
12812 zda,
12813 zn,
12814 ReadVRegister(instr->ExtractBits(19, 16)),
12815 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012816 break;
12817 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012818 udot(vform,
12819 zda,
12820 zn,
12821 ReadVRegister(instr->ExtractBits(18, 16)),
12822 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012823 break;
12824 default:
12825 VIXL_UNIMPLEMENTED();
12826 break;
12827 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012828}
12829
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012830void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012831 SimPRegister& pd = ReadPRegister(instr->GetPd());
12832 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12833 SimPRegister& pn = ReadPRegister(instr->GetPn());
12834 SimPRegister result;
12835
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012836 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012837 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012838 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012839 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012840 break;
12841 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012842 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012843 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012844 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012845 default:
12846 VIXL_UNIMPLEMENTED();
12847 break;
12848 }
TatWai Chong5d872292020-01-02 15:39:51 -080012849
12850 if (instr->ExtractBit(4) == 1) {
12851 mov_merging(pd, pg, result);
12852 } else {
12853 mov_zeroing(pd, pg, result);
12854 }
12855
12856 // Set flag if needed.
12857 if (instr->ExtractBit(22) == 1) {
12858 PredTest(kFormatVnB, pg, pd);
12859 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012860}
12861
12862void Simulator::VisitSVEPropagateBreakToNextPartition(
12863 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012864 SimPRegister& pdm = ReadPRegister(instr->GetPd());
12865 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12866 SimPRegister& pn = ReadPRegister(instr->GetPn());
12867
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012868 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012869 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012870 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080012871 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012872 break;
12873 default:
12874 VIXL_UNIMPLEMENTED();
12875 break;
12876 }
TatWai Chong5d872292020-01-02 15:39:51 -080012877
12878 // Set flag if needed.
12879 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010012880 // Note that this ignores `pg`.
12881 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080012882 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012883}
12884
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012885void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012886 SimPRegister& pd = ReadPRegister(instr->GetPd());
12887 SimPRegister& pn = ReadPRegister(instr->GetPn());
12888
12889 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12890 SimVRegister zero;
12891 dup_immediate(kFormatVnB, zero, 0);
12892
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012893 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012894 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012895 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012896 break;
12897 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012898 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012899 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012900 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012901 VIXL_UNIMPLEMENTED();
12902 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012903 }
TatWai Chong47c26842020-02-10 01:51:32 -080012904 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012905}
12906
12907void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012908 VectorFormat vform = instr->GetSVEVectorFormat();
12909 SimPRegister& pd = ReadPRegister(instr->GetPd());
12910 SimPRegister& pn = ReadPRegister(instr->GetPn());
12911 SimPRegister& pm = ReadPRegister(instr->GetPm());
12912
12913 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12914 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12915
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012916 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012917 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012918 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012919 break;
12920 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012921 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012922 break;
12923 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012924 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012925 break;
12926 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012927 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012928 break;
12929 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012930 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012931 break;
12932 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012933 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012934 break;
12935 default:
12936 VIXL_UNIMPLEMENTED();
12937 break;
12938 }
TatWai Chong47c26842020-02-10 01:51:32 -080012939 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012940}
12941
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012942void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012943 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012944 case REV_p_p: {
12945 VectorFormat vform = instr->GetSVEVectorFormat();
12946 SimPRegister& pn = ReadPRegister(instr->GetPn());
12947 SimPRegister& pd = ReadPRegister(instr->GetPd());
12948 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12949 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080012950 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012951 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012952 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012953 default:
12954 VIXL_UNIMPLEMENTED();
12955 break;
12956 }
12957}
12958
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012959void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000012960 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12961 // Second source register "Zm" is encoded where "Zn" would usually be.
12962 SimVRegister& zm = ReadVRegister(instr->GetRn());
12963
12964 const int imm8h_mask = 0x001F0000;
12965 const int imm8l_mask = 0x00001C00;
12966 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
12967 int vl = GetVectorLengthInBytes();
12968 index = (index >= vl) ? 0 : index;
12969
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012970 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
12971 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000012972 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012973 break;
12974 default:
12975 VIXL_UNIMPLEMENTED();
12976 break;
12977 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012978}
12979
12980void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000012981 VectorFormat vform = instr->GetSVEVectorFormat();
12982 SimVRegister& zd = ReadVRegister(instr->GetRd());
12983 SimVRegister& zn = ReadVRegister(instr->GetRn());
12984 SimVRegister& zm = ReadVRegister(instr->GetRm());
12985
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012986 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
12987 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012988 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012989 break;
12990 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012991 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012992 break;
12993 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012994 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012995 break;
12996 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012997 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012998 break;
12999 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000013000 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013001 break;
13002 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000013003 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013004 break;
13005 default:
13006 VIXL_UNIMPLEMENTED();
13007 break;
13008 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013009}
13010
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013011void Simulator::VisitSVEConditionallyBroadcastElementToVector(
13012 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013013 VectorFormat vform = instr->GetSVEVectorFormat();
13014 SimVRegister& zdn = ReadVRegister(instr->GetRd());
13015 SimVRegister& zm = ReadVRegister(instr->GetRn());
13016 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13017
13018 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013019 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013020 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000013021 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013022 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013023 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000013024 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013025 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013026 default:
13027 VIXL_UNIMPLEMENTED();
13028 break;
13029 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013030
13031 if (active_offset >= 0) {
13032 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13033 if (value.first) {
13034 dup_immediate(vform, zdn, value.second);
13035 } else {
13036 // Trigger a line of trace for the operation, even though it doesn't
13037 // change the register value.
13038 mov(vform, zdn, zdn);
13039 }
13040 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013041}
13042
13043void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
13044 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013045 VectorFormat vform = instr->GetSVEVectorFormat();
13046 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13047 SimVRegister& zm = ReadVRegister(instr->GetRn());
13048 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13049
13050 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013051 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
13052 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013053 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013054 break;
13055 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013056 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013057 break;
13058 default:
13059 VIXL_UNIMPLEMENTED();
13060 break;
13061 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013062
13063 if (active_offset >= 0) {
13064 LogicVRegister dst(vdn);
13065 uint64_t src1_value = dst.Uint(vform, 0);
13066 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
13067 dup_immediate(vform, vdn, 0);
13068 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
13069 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013070}
13071
13072void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
13073 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013074 VectorFormat vform = instr->GetSVEVectorFormat();
13075 SimVRegister& zm = ReadVRegister(instr->GetRn());
13076 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13077
13078 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013079 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
13080 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013081 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013082 break;
13083 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013084 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013085 break;
13086 default:
13087 VIXL_UNIMPLEMENTED();
13088 break;
13089 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013090
13091 if (active_offset >= 0) {
13092 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13093 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13094 GetUintMask(LaneSizeInBitsFromFormat(vform));
13095 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13096 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013097}
13098
13099void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13100 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013101 VectorFormat vform = instr->GetSVEVectorFormat();
13102 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13103 SimVRegister& zm = ReadVRegister(instr->GetRn());
13104 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13105
13106 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013107 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13108 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013109 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013110 break;
13111 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013112 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013113 break;
13114 default:
13115 VIXL_UNIMPLEMENTED();
13116 break;
13117 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013118
13119 if (active_offset >= 0) {
13120 LogicVRegister dst(vdn);
13121 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13122 dup_immediate(vform, vdn, 0);
13123 dst.SetUint(vform, 0, value.second);
13124 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013125}
13126
13127void Simulator::VisitSVEExtractElementToGeneralRegister(
13128 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013129 VectorFormat vform = instr->GetSVEVectorFormat();
13130 SimVRegister& zm = ReadVRegister(instr->GetRn());
13131 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13132
13133 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013134 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13135 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013136 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013137 break;
13138 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013139 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013140 break;
13141 default:
13142 VIXL_UNIMPLEMENTED();
13143 break;
13144 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013145
13146 if (active_offset >= 0) {
13147 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13148 WriteXRegister(instr->GetRd(), value.second);
13149 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013150}
13151
13152void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013153 VectorFormat vform = instr->GetSVEVectorFormat();
13154 SimVRegister& zd = ReadVRegister(instr->GetRd());
13155 SimVRegister& zn = ReadVRegister(instr->GetRn());
13156 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13157
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013158 switch (instr->Mask(SVECompressActiveElementsMask)) {
13159 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013160 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013161 break;
13162 default:
13163 VIXL_UNIMPLEMENTED();
13164 break;
13165 }
13166}
13167
13168void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13169 const Instruction* instr) {
13170 VectorFormat vform = instr->GetSVEVectorFormat();
13171 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13172 SimVRegister z_result;
13173
13174 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013175 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010013176 dup_immediate(vform,
13177 z_result,
13178 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13179 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013180 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013181 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013182 VIXL_UNIMPLEMENTED();
13183 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013184 }
13185}
13186
13187void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013188 VectorFormat vform = instr->GetSVEVectorFormat();
13189 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13190 SimVRegister& zd = ReadVRegister(instr->GetRd());
13191
13192 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013193 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013194 case CPY_z_p_i: {
13195 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
13196 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13197 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013198 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013199 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013200 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013201 VIXL_UNIMPLEMENTED();
13202 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013203 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013204
13205 if (instr->ExtractBit(14) != 0) {
13206 mov_merging(vform, zd, pg, result);
13207 } else {
13208 mov_zeroing(vform, zd, pg, result);
13209 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013210}
13211
13212void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000013213 SimVRegister& zd = ReadVRegister(instr->GetRd());
13214 SimVRegister& zn = ReadVRegister(instr->GetRn());
13215 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13216 SimVRegister result;
13217
13218 // In NEON, the chunk size in which elements are REVersed is in the
13219 // instruction mnemonic, and the element size attached to the register.
13220 // SVE reverses the semantics; the mapping to logic functions below is to
13221 // account for this.
13222 VectorFormat chunk_form = instr->GetSVEVectorFormat();
13223 VectorFormat element_form = kFormatUndefined;
13224
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013225 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013226 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013227 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013228 break;
13229 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013230 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13231 (chunk_form == kFormatVnD));
13232 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013233 break;
13234 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013235 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13236 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013237 break;
13238 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013239 VIXL_ASSERT(chunk_form == kFormatVnD);
13240 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013241 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013242 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013243 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013244 break;
13245 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000013246
13247 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13248 VIXL_ASSERT(element_form != kFormatUndefined);
13249 switch (chunk_form) {
13250 case kFormatVnH:
13251 rev16(element_form, result, zn);
13252 break;
13253 case kFormatVnS:
13254 rev32(element_form, result, zn);
13255 break;
13256 case kFormatVnD:
13257 rev64(element_form, result, zn);
13258 break;
13259 default:
13260 VIXL_UNIMPLEMENTED();
13261 }
13262 }
13263
13264 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013265}
13266
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013267void Simulator::VisitSVEVectorSplice(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013268 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013269 SimVRegister& zd = ReadVRegister(instr->GetRd());
13270 SimVRegister& zn = ReadVRegister(instr->GetRn());
13271 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
Martyn Capewellf804b602020-02-24 18:57:18 +000013272 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13273
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013274 switch (form_hash_) {
13275 case Hash("splice_z_p_zz_des"):
13276 splice(vform, zd, pg, zd, zn);
13277 break;
13278 case Hash("splice_z_p_zz_con"):
13279 splice(vform, zd, pg, zn, zn2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013280 break;
13281 default:
13282 VIXL_UNIMPLEMENTED();
13283 break;
13284 }
13285}
TatWai Chong4f28df72019-08-14 17:50:30 -070013286
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013287void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13288 SimVRegister& zd = ReadVRegister(instr->GetRd());
13289 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13290 case DUP_z_r:
13291 dup_immediate(instr->GetSVEVectorFormat(),
13292 zd,
13293 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13294 break;
13295 default:
13296 VIXL_UNIMPLEMENTED();
13297 break;
13298 }
13299}
13300
13301void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13302 SimVRegister& zd = ReadVRegister(instr->GetRd());
13303 VectorFormat vform = instr->GetSVEVectorFormat();
13304 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13305 case INSR_z_v:
13306 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13307 break;
13308 default:
13309 VIXL_UNIMPLEMENTED();
13310 break;
13311 }
13312}
13313
13314void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13315 SimVRegister& zd = ReadVRegister(instr->GetRd());
13316 VectorFormat vform = instr->GetSVEVectorFormat();
13317 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13318 case INSR_z_r:
13319 insr(vform, zd, ReadXRegister(instr->GetRn()));
13320 break;
13321 default:
13322 VIXL_UNIMPLEMENTED();
13323 break;
13324 }
13325}
13326
13327void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13328 SimVRegister& zd = ReadVRegister(instr->GetRd());
13329 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070013330 case DUP_z_zi: {
13331 std::pair<int, int> index_and_lane_size =
13332 instr->GetSVEPermuteIndexAndLaneSizeLog2();
13333 int index = index_and_lane_size.first;
13334 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13335 VectorFormat vform =
13336 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13337 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13338 // Out of bounds, set the destination register to zero.
13339 dup_immediate(kFormatVnD, zd, 0);
13340 } else {
13341 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13342 }
13343 return;
13344 }
TatWai Chong4f28df72019-08-14 17:50:30 -070013345 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013346 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070013347 break;
13348 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013349}
TatWai Chong4f28df72019-08-14 17:50:30 -070013350
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013351void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13352 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070013353 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013354 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013355 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013356 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013357 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013358 default:
13359 VIXL_UNIMPLEMENTED();
13360 break;
13361 }
13362}
13363
13364void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13365 SimVRegister& zd = ReadVRegister(instr->GetRd());
13366 VectorFormat vform = instr->GetSVEVectorFormat();
13367 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013368 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013369 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013370 break;
13371 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013372 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013373 break;
13374 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013375 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013376 break;
13377 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013378 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13379 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013380 default:
13381 VIXL_UNIMPLEMENTED();
13382 break;
13383 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013384}
13385
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013386void Simulator::VisitSVETableLookup(const Instruction* instr) {
Martyn Capewell99c60492020-10-30 08:14:39 +000013387 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013388 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell99c60492020-10-30 08:14:39 +000013389 SimVRegister& zn = ReadVRegister(instr->GetRn());
13390 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13391 SimVRegister& zm = ReadVRegister(instr->GetRm());
13392
13393 switch (form_hash_) {
13394 case Hash("tbl_z_zz_1"):
13395 tbl(vform, zd, zn, zm);
13396 break;
13397 case Hash("tbl_z_zz_2"):
13398 tbl(vform, zd, zn, zn2, zm);
13399 break;
13400 case Hash("tbx_z_zz"):
13401 tbx(vform, zd, zn, zm);
13402 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013403 default:
Martyn Capewell99c60492020-10-30 08:14:39 +000013404 VIXL_UNIMPLEMENTED();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013405 break;
13406 }
13407}
13408
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013409void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013410 VectorFormat vform = instr->GetSVEVectorFormat();
13411 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13412 SimPRegister& pn = ReadPRegister(instr->GetPn());
13413
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013414 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013415 case CNTP_r_p_p: {
13416 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013417 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013418 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013419 default:
13420 VIXL_UNIMPLEMENTED();
13421 break;
13422 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013423}
13424
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013425void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13426 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080013427 SimPRegister& pd = ReadPRegister(instr->GetPd());
13428 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13429 SimPRegister& pn = ReadPRegister(instr->GetPn());
13430 SimPRegister& pm = ReadPRegister(instr->GetPm());
13431 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070013432 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013433 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013434 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013435 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013436 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013437 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013438 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013439 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013440 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013441 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013442 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013443 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013444 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013445 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013446 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070013447 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080013448 result,
13449 pn,
13450 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013451 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080013452 case SEL_p_p_pp:
13453 sel(pd, pg, pn, pm);
13454 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013455 default:
13456 VIXL_UNIMPLEMENTED();
13457 break;
13458 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013459
13460 mov_zeroing(pd, pg, result);
13461 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13462 PredTest(kFormatVnB, pg, pd);
13463 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013464}
13465
Jacob Bramley0ce75842019-07-17 18:12:50 +010013466void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013467 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13468 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13469 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013470 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010013471 pfirst(pdn, pg, pdn);
13472 // TODO: Is this broken when pg == pdn?
13473 PredTest(kFormatVnB, pg, pdn);
13474 break;
13475 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013476 VIXL_UNIMPLEMENTED();
13477 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013478 }
13479}
13480
13481void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013482 // This group only contains PTRUE{S}, and there are no unallocated encodings.
13483 VIXL_STATIC_ASSERT(
13484 SVEPredicateInitializeMask ==
13485 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13486 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13487 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13488
13489 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13490 VectorFormat vform = instr->GetSVEVectorFormat();
13491
13492 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13493 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13494}
13495
13496void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013497 // This group only contains PNEXT, and there are no unallocated encodings.
13498 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13499 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13500
13501 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13502 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13503 VectorFormat vform = instr->GetSVEVectorFormat();
13504
13505 pnext(vform, pdn, pg, pdn);
13506 // TODO: Is this broken when pg == pdn?
13507 PredTest(vform, pg, pdn);
13508}
13509
13510void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13511 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080013512 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13513 LogicPRegister pg(ReadPRegister(instr->GetPn()));
13514 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013515 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13516 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013517 // Do nothing.
13518 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013519 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013520 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013521 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013522 default:
13523 VIXL_UNIMPLEMENTED();
13524 break;
13525 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013526
13527 LogicPRegister ffr(ReadFFR());
13528 mov_zeroing(pd, pg, ffr);
13529
13530 if (flags == SetFlags) {
13531 PredTest(kFormatVnB, pg, pd);
13532 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010013533}
13534
13535void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13536 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013537 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13538 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010013539 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013540 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080013541 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013542 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013543 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013544 VIXL_UNIMPLEMENTED();
13545 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013546 }
13547}
13548
13549void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013550 switch (instr->Mask(SVEPredicateTestMask)) {
13551 case PTEST_p_p:
13552 PredTest(kFormatVnB,
13553 ReadPRegister(instr->ExtractBits(13, 10)),
13554 ReadPRegister(instr->GetPn()));
13555 break;
13556 default:
13557 VIXL_UNIMPLEMENTED();
13558 break;
13559 }
13560}
13561
13562void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013563 switch (instr->Mask(SVEPredicateZeroMask)) {
13564 case PFALSE_p:
13565 pfalse(ReadPRegister(instr->GetPd()));
13566 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013567 default:
13568 VIXL_UNIMPLEMENTED();
13569 break;
13570 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013571}
13572
13573void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080013574 SimPRegister& pd = ReadPRegister(instr->GetPd());
13575 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13576 SimPRegister& pn = ReadPRegister(instr->GetPn());
13577 SimPRegister& pm = ReadPRegister(instr->GetPm());
13578
13579 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013580 switch (instr->Mask(SVEPropagateBreakMask)) {
13581 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013582 set_flags = true;
13583 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013584 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013585 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013586 break;
13587 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013588 set_flags = true;
13589 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013590 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013591 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013592 break;
13593 default:
13594 VIXL_UNIMPLEMENTED();
13595 break;
13596 }
TatWai Chong38303d92019-12-02 15:49:29 -080013597
13598 if (set_flags) {
13599 PredTest(kFormatVnB, pg, pd);
13600 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013601}
13602
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013603void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13604 uint64_t length = 0;
13605 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13606 case ADDPL_r_ri:
13607 length = GetPredicateLengthInBytes();
13608 break;
13609 case ADDVL_r_ri:
13610 length = GetVectorLengthInBytes();
13611 break;
13612 default:
13613 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013614 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013615 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013616 WriteXRegister(instr->GetRd(),
13617 base + (length * instr->GetImmSVEVLScale()),
13618 LogRegWrites,
13619 Reg31IsStackPointer);
13620}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013621
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013622void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13623 int64_t scale = instr->GetImmSVEVLScale();
13624
13625 switch (instr->Mask(SVEStackFrameSizeMask)) {
13626 case RDVL_r_i:
13627 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13628 break;
13629 default:
13630 VIXL_UNIMPLEMENTED();
13631 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013632}
13633
13634void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013635 // The only instruction in this group is `sel`, and there are no unused
13636 // encodings.
13637 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13638
13639 VectorFormat vform = instr->GetSVEVectorFormat();
13640 SimVRegister& zd = ReadVRegister(instr->GetRd());
13641 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13642 SimVRegister& zn = ReadVRegister(instr->GetRn());
13643 SimVRegister& zm = ReadVRegister(instr->GetRm());
13644
13645 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013646}
13647
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013648void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013649 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013650 case SETFFR_f: {
13651 LogicPRegister ffr(ReadFFR());
13652 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013653 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013654 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013655 default:
13656 VIXL_UNIMPLEMENTED();
13657 break;
13658 }
13659}
13660
13661void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013662 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013663 case WRFFR_f_p: {
13664 SimPRegister pn(ReadPRegister(instr->GetPn()));
13665 bool last_active = true;
13666 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13667 bool active = pn.GetBit(i);
13668 if (active && !last_active) {
13669 // `pn` is non-monotonic. This is UNPREDICTABLE.
13670 VIXL_ABORT();
13671 }
13672 last_active = active;
13673 }
13674 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013675 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013676 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013677 default:
13678 VIXL_UNIMPLEMENTED();
13679 break;
13680 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013681}
Alexandre Ramesd3832962016-07-04 15:03:43 +010013682
TatWai Chong6205eb42019-09-24 10:07:20 +010013683void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013684 bool is_signed;
13685 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13686 case LD1B_z_p_bi_u8:
13687 case LD1B_z_p_bi_u16:
13688 case LD1B_z_p_bi_u32:
13689 case LD1B_z_p_bi_u64:
13690 case LD1H_z_p_bi_u16:
13691 case LD1H_z_p_bi_u32:
13692 case LD1H_z_p_bi_u64:
13693 case LD1W_z_p_bi_u32:
13694 case LD1W_z_p_bi_u64:
13695 case LD1D_z_p_bi_u64:
13696 is_signed = false;
13697 break;
13698 case LD1SB_z_p_bi_s16:
13699 case LD1SB_z_p_bi_s32:
13700 case LD1SB_z_p_bi_s64:
13701 case LD1SH_z_p_bi_s32:
13702 case LD1SH_z_p_bi_s64:
13703 case LD1SW_z_p_bi_s64:
13704 is_signed = true;
13705 break;
13706 default:
13707 // This encoding group is complete, so no other values should be possible.
13708 VIXL_UNREACHABLE();
13709 is_signed = false;
13710 break;
13711 }
13712
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013713 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010013714 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13715 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013716 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13717 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13718 uint64_t offset =
13719 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013720 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013721 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013722 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13723 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013724 ReadPRegister(instr->GetPgLow8()),
13725 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013726 addr,
13727 is_signed);
13728}
13729
13730void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13731 const Instruction* instr) {
13732 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010013733 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13734 case LD1B_z_p_br_u8:
13735 case LD1B_z_p_br_u16:
13736 case LD1B_z_p_br_u32:
13737 case LD1B_z_p_br_u64:
13738 case LD1H_z_p_br_u16:
13739 case LD1H_z_p_br_u32:
13740 case LD1H_z_p_br_u64:
13741 case LD1W_z_p_br_u32:
13742 case LD1W_z_p_br_u64:
13743 case LD1D_z_p_br_u64:
13744 is_signed = false;
13745 break;
13746 case LD1SB_z_p_br_s16:
13747 case LD1SB_z_p_br_s32:
13748 case LD1SB_z_p_br_s64:
13749 case LD1SH_z_p_br_s32:
13750 case LD1SH_z_p_br_s64:
13751 case LD1SW_z_p_br_s64:
13752 is_signed = true;
13753 break;
13754 default:
13755 // This encoding group is complete, so no other values should be possible.
13756 VIXL_UNREACHABLE();
13757 is_signed = false;
13758 break;
13759 }
13760
13761 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13762 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13763 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13764 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13765 uint64_t offset = ReadXRegister(instr->GetRm());
13766 offset <<= msize_in_bytes_log2;
13767 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013768 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13769 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013770 ReadPRegister(instr->GetPgLow8()),
13771 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013772 addr,
13773 is_signed);
13774}
13775
Alexandre Ramesd3832962016-07-04 15:03:43 +010013776void Simulator::DoUnreachable(const Instruction* instr) {
13777 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13778 (instr->GetImmException() == kUnreachableOpcode));
13779
13780 fprintf(stream_,
13781 "Hit UNREACHABLE marker at pc=%p.\n",
13782 reinterpret_cast<const void*>(instr));
13783 abort();
13784}
13785
13786
13787void Simulator::DoTrace(const Instruction* instr) {
13788 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13789 (instr->GetImmException() == kTraceOpcode));
13790
13791 // Read the arguments encoded inline in the instruction stream.
13792 uint32_t parameters;
13793 uint32_t command;
13794
13795 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13796 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13797 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13798
13799 switch (command) {
13800 case TRACE_ENABLE:
13801 SetTraceParameters(GetTraceParameters() | parameters);
13802 break;
13803 case TRACE_DISABLE:
13804 SetTraceParameters(GetTraceParameters() & ~parameters);
13805 break;
13806 default:
13807 VIXL_UNREACHABLE();
13808 }
13809
13810 WritePc(instr->GetInstructionAtOffset(kTraceLength));
13811}
13812
13813
13814void Simulator::DoLog(const Instruction* instr) {
13815 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13816 (instr->GetImmException() == kLogOpcode));
13817
13818 // Read the arguments encoded inline in the instruction stream.
13819 uint32_t parameters;
13820
13821 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13822 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13823
13824 // We don't support a one-shot LOG_DISASM.
13825 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13826 // Print the requested information.
13827 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13828 if (parameters & LOG_REGS) PrintRegisters();
13829 if (parameters & LOG_VREGS) PrintVRegisters();
13830
13831 WritePc(instr->GetInstructionAtOffset(kLogLength));
13832}
13833
13834
13835void Simulator::DoPrintf(const Instruction* instr) {
13836 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13837 (instr->GetImmException() == kPrintfOpcode));
13838
13839 // Read the arguments encoded inline in the instruction stream.
13840 uint32_t arg_count;
13841 uint32_t arg_pattern_list;
13842 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13843 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13844 memcpy(&arg_pattern_list,
13845 instr + kPrintfArgPatternListOffset,
13846 sizeof(arg_pattern_list));
13847
13848 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13849 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13850
13851 // We need to call the host printf function with a set of arguments defined by
13852 // arg_pattern_list. Because we don't know the types and sizes of the
13853 // arguments, this is very difficult to do in a robust and portable way. To
13854 // work around the problem, we pick apart the format string, and print one
13855 // format placeholder at a time.
13856
13857 // Allocate space for the format string. We take a copy, so we can modify it.
13858 // Leave enough space for one extra character per expected argument (plus the
13859 // '\0' termination).
13860 const char* format_base = ReadRegister<const char*>(0);
13861 VIXL_ASSERT(format_base != NULL);
13862 size_t length = strlen(format_base) + 1;
13863 char* const format = new char[length + arg_count];
13864
13865 // A list of chunks, each with exactly one format placeholder.
13866 const char* chunks[kPrintfMaxArgCount];
13867
13868 // Copy the format string and search for format placeholders.
13869 uint32_t placeholder_count = 0;
13870 char* format_scratch = format;
13871 for (size_t i = 0; i < length; i++) {
13872 if (format_base[i] != '%') {
13873 *format_scratch++ = format_base[i];
13874 } else {
13875 if (format_base[i + 1] == '%') {
13876 // Ignore explicit "%%" sequences.
13877 *format_scratch++ = format_base[i];
13878 i++;
13879 // Chunks after the first are passed as format strings to printf, so we
13880 // need to escape '%' characters in those chunks.
13881 if (placeholder_count > 0) *format_scratch++ = format_base[i];
13882 } else {
13883 VIXL_CHECK(placeholder_count < arg_count);
13884 // Insert '\0' before placeholders, and store their locations.
13885 *format_scratch++ = '\0';
13886 chunks[placeholder_count++] = format_scratch;
13887 *format_scratch++ = format_base[i];
13888 }
13889 }
13890 }
13891 VIXL_CHECK(placeholder_count == arg_count);
13892
13893 // Finally, call printf with each chunk, passing the appropriate register
13894 // argument. Normally, printf returns the number of bytes transmitted, so we
13895 // can emulate a single printf call by adding the result from each chunk. If
13896 // any call returns a negative (error) value, though, just return that value.
13897
13898 printf("%s", clr_printf);
13899
13900 // Because '\0' is inserted before each placeholder, the first string in
13901 // 'format' contains no format placeholders and should be printed literally.
13902 int result = printf("%s", format);
13903 int pcs_r = 1; // Start at x1. x0 holds the format string.
13904 int pcs_f = 0; // Start at d0.
13905 if (result >= 0) {
13906 for (uint32_t i = 0; i < placeholder_count; i++) {
13907 int part_result = -1;
13908
13909 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13910 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13911 switch (arg_pattern) {
13912 case kPrintfArgW:
13913 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13914 break;
13915 case kPrintfArgX:
13916 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13917 break;
13918 case kPrintfArgD:
13919 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13920 break;
13921 default:
13922 VIXL_UNREACHABLE();
13923 }
13924
13925 if (part_result < 0) {
13926 // Handle error values.
13927 result = part_result;
13928 break;
13929 }
13930
13931 result += part_result;
13932 }
13933 }
13934
13935 printf("%s", clr_normal);
13936
13937 // Printf returns its result in x0 (just like the C library's printf).
13938 WriteXRegister(0, result);
13939
13940 // The printf parameters are inlined in the code, so skip them.
13941 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13942
13943 // Set LR as if we'd just called a native printf function.
13944 WriteLr(ReadPc());
13945
13946 delete[] format;
13947}
13948
Alexandre Rames064e02d2016-07-12 11:53:13 +010013949
Alexandre Ramesca73ba02016-07-28 09:16:03 +010013950#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010013951void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013952 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013953 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13954 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013955 uintptr_t call_wrapper_address =
13956 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13957 uintptr_t function_address =
13958 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080013959 RuntimeCallType call_type = static_cast<RuntimeCallType>(
13960 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013961 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010013962 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013963
13964 if (call_type == kCallRuntime) {
13965 WriteRegister(kLinkRegCode,
13966 instr->GetInstructionAtOffset(kRuntimeCallLength));
13967 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013968 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013969 // Read the return address from `lr` and write it into `pc`.
13970 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013971}
13972#else
13973void Simulator::DoRuntimeCall(const Instruction* instr) {
13974 USE(instr);
13975 VIXL_UNREACHABLE();
13976}
13977#endif
13978
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013979
13980void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
13981 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
13982
13983 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013984 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013985 std::numeric_limits<ElementType>::max());
13986
13987 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
13988
13989 size_t element_size = sizeof(ElementType);
13990 size_t offset = kConfigureCPUFeaturesListOffset;
13991
13992 // Read the kNone-terminated list of features.
13993 CPUFeatures parameters;
13994 while (true) {
13995 ElementType feature = Memory::Read<ElementType>(instr + offset);
13996 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013997 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013998 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
13999 }
14000
14001 switch (instr->GetImmException()) {
14002 case kSetCPUFeaturesOpcode:
14003 SetCPUFeatures(parameters);
14004 break;
14005 case kEnableCPUFeaturesOpcode:
14006 GetCPUFeatures()->Combine(parameters);
14007 break;
14008 case kDisableCPUFeaturesOpcode:
14009 GetCPUFeatures()->Remove(parameters);
14010 break;
14011 default:
14012 VIXL_UNREACHABLE();
14013 break;
14014 }
14015
14016 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
14017}
14018
14019
14020void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
14021 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14022 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
14023 USE(instr);
14024
14025 saved_cpu_features_.push_back(*GetCPUFeatures());
14026}
14027
14028
14029void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
14030 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14031 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
14032 USE(instr);
14033
14034 SetCPUFeatures(saved_cpu_features_.back());
14035 saved_cpu_features_.pop_back();
14036}
14037
14038
Alexandre Ramesd3832962016-07-04 15:03:43 +010014039} // namespace aarch64
14040} // namespace vixl
14041
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010014042#endif // VIXL_INCLUDE_SIMULATOR_AARCH64