blob: 598a334e7c94b8f169481a92021ca00dfd6acdd8 [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},
130 {"mla_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
131 {"mla_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
132 {"mla_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
133 {"mls_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnD_ZmD_imm},
134 {"mls_z_zzzi_h", &Simulator::Simulate_ZdaH_ZnH_ZmH_imm},
135 {"mls_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnS_ZmS_imm},
136 {"mul_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
137 {"mul_z_zzi_d", &Simulator::Simulate_ZdD_ZnD_ZmD_imm},
138 {"mul_z_zzi_h", &Simulator::Simulate_ZdH_ZnH_ZmH_imm},
139 {"mul_z_zzi_s", &Simulator::Simulate_ZdS_ZnS_ZmS_imm},
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},
191 {"splice_z_p_zz_con", &Simulator::Simulate_ZdT_Pg_Zn1T_Zn2T},
192 {"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) {
1912 SimPRegister& pd = ReadPRegister(instr->GetPd());
1913 USE(pd);
1914
1915 switch (form_hash_) {
1916 case Hash("whilerw_p_rr"):
1917 VIXL_UNIMPLEMENTED();
1918 break;
1919 case Hash("whilewr_p_rr"):
1920 VIXL_UNIMPLEMENTED();
1921 break;
1922 default:
1923 VIXL_UNIMPLEMENTED();
1924 }
1925}
1926
1927void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
1928 SimVRegister& zd = ReadVRegister(instr->GetRd());
1929 USE(zd);
1930 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
1931 USE(zn1);
1932
1933 switch (form_hash_) {
1934 case Hash("ext_z_zi_con"):
1935 VIXL_UNIMPLEMENTED();
1936 break;
1937 default:
1938 VIXL_UNIMPLEMENTED();
1939 }
1940}
1941
1942void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
1943 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001944 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001945 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001946
1947 switch (form_hash_) {
1948 case Hash("histseg_z_zz"):
Martyn Capewell710ec6f2020-10-22 16:56:17 +01001949 if (instr->GetSVEVectorFormat() == kFormatVnB) {
1950 histogram(kFormatVnB,
1951 zd,
1952 GetPTrue(),
1953 zn,
1954 zm,
1955 /* do_segmented = */ true);
1956 } else {
1957 VIXL_UNIMPLEMENTED();
1958 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01001959 break;
1960 case Hash("pmul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07001961 pmul(kFormatVnB, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001962 break;
1963 default:
1964 VIXL_UNIMPLEMENTED();
1965 }
1966}
1967
1968void Simulator::Simulate_ZdD_PgM_ZnS(const Instruction* instr) {
1969 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
1970 USE(pg);
1971 SimVRegister& zd = ReadVRegister(instr->GetRd());
1972 USE(zd);
1973 SimVRegister& zn = ReadVRegister(instr->GetRn());
1974 USE(zn);
1975
1976 switch (form_hash_) {
1977 case Hash("fcvtlt_z_p_z_s2d"):
1978 VIXL_UNIMPLEMENTED();
1979 break;
1980 default:
1981 VIXL_UNIMPLEMENTED();
1982 }
1983}
1984
1985void Simulator::Simulate_ZdD_ZnD_ZmD_imm(const Instruction* instr) {
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("mul_z_zzi_d"):
1993 VIXL_UNIMPLEMENTED();
1994 break;
1995 case Hash("sqdmulh_z_zzi_d"):
1996 VIXL_UNIMPLEMENTED();
1997 break;
1998 case Hash("sqrdmulh_z_zzi_d"):
1999 VIXL_UNIMPLEMENTED();
2000 break;
2001 default:
2002 VIXL_UNIMPLEMENTED();
2003 }
2004}
2005
TatWai Chong1719b712020-09-25 18:16:40 -07002006void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002007 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong1719b712020-09-25 18:16:40 -07002008 SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
Martyn Capewell6bf28752020-08-05 11:57:06 +01002009 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong1719b712020-09-25 18:16:40 -07002010
2011 SimVRegister temp, zm_idx, zn_b, zn_t;
2012 // Instead of calling the indexed form of the instruction logic, we call the
2013 // vector form, which can reuse existing function logics without modification.
Martyn Capewell97ca8062020-10-23 14:45:14 +01002014 // Select the specified elements based on the index input and than pack them
2015 // to the corresponding position.
TatWai Chong1719b712020-09-25 18:16:40 -07002016 Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
2017 dup_elements_to_segments(kFormatVnS, temp, zm, index);
2018 pack_even_elements(kFormatVnS, zm_idx, temp);
2019
2020 pack_even_elements(kFormatVnS, zn_b, zn);
2021 pack_odd_elements(kFormatVnS, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002022
2023 switch (form_hash_) {
2024 case Hash("smullb_z_zzi_d"):
2025 VIXL_UNIMPLEMENTED();
2026 break;
2027 case Hash("smullt_z_zzi_d"):
2028 VIXL_UNIMPLEMENTED();
2029 break;
2030 case Hash("sqdmullb_z_zzi_d"):
TatWai Chong1719b712020-09-25 18:16:40 -07002031 sqdmull(kFormatVnD, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002032 break;
2033 case Hash("sqdmullt_z_zzi_d"):
TatWai Chong1719b712020-09-25 18:16:40 -07002034 sqdmull(kFormatVnD, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002035 break;
2036 case Hash("umullb_z_zzi_d"):
2037 VIXL_UNIMPLEMENTED();
2038 break;
2039 case Hash("umullt_z_zzi_d"):
2040 VIXL_UNIMPLEMENTED();
2041 break;
2042 default:
2043 VIXL_UNIMPLEMENTED();
2044 }
2045}
2046
2047void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2048 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2049 USE(pg);
2050 SimVRegister& zd = ReadVRegister(instr->GetRd());
2051 USE(zd);
2052 SimVRegister& zn = ReadVRegister(instr->GetRn());
2053 USE(zn);
2054
2055 switch (form_hash_) {
2056 case Hash("fcvtnt_z_p_z_s2h"):
2057 VIXL_UNIMPLEMENTED();
2058 break;
2059 default:
2060 VIXL_UNIMPLEMENTED();
2061 }
2062}
2063
2064void Simulator::Simulate_ZdH_ZnH_ZmH_imm(const Instruction* instr) {
2065 SimVRegister& zd = ReadVRegister(instr->GetRd());
2066 USE(zd);
2067 SimVRegister& zn = ReadVRegister(instr->GetRn());
2068 USE(zn);
2069
2070 switch (form_hash_) {
2071 case Hash("mul_z_zzi_h"):
2072 VIXL_UNIMPLEMENTED();
2073 break;
2074 case Hash("sqdmulh_z_zzi_h"):
2075 VIXL_UNIMPLEMENTED();
2076 break;
2077 case Hash("sqrdmulh_z_zzi_h"):
2078 VIXL_UNIMPLEMENTED();
2079 break;
2080 default:
2081 VIXL_UNIMPLEMENTED();
2082 }
2083}
2084
2085void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2086 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2087 USE(pg);
2088 SimVRegister& zd = ReadVRegister(instr->GetRd());
2089 USE(zd);
2090 SimVRegister& zn = ReadVRegister(instr->GetRn());
2091 USE(zn);
2092
2093 switch (form_hash_) {
2094 case Hash("fcvtnt_z_p_z_d2s"):
2095 VIXL_UNIMPLEMENTED();
2096 break;
2097 case Hash("fcvtx_z_p_z_d2s"):
2098 VIXL_UNIMPLEMENTED();
2099 break;
2100 case Hash("fcvtxnt_z_p_z_d2s"):
2101 VIXL_UNIMPLEMENTED();
2102 break;
2103 default:
2104 VIXL_UNIMPLEMENTED();
2105 }
2106}
2107
2108void Simulator::Simulate_ZdS_PgM_ZnH(const Instruction* instr) {
2109 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2110 USE(pg);
2111 SimVRegister& zd = ReadVRegister(instr->GetRd());
2112 USE(zd);
2113 SimVRegister& zn = ReadVRegister(instr->GetRn());
2114 USE(zn);
2115
2116 switch (form_hash_) {
2117 case Hash("fcvtlt_z_p_z_h2s"):
2118 VIXL_UNIMPLEMENTED();
2119 break;
2120 default:
2121 VIXL_UNIMPLEMENTED();
2122 }
2123}
2124
2125void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002126 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002127 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002128 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002129 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002130 SimVRegister result;
2131
2132 if (vform != kFormatVnS) {
2133 VIXL_UNIMPLEMENTED();
2134 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002135
2136 switch (form_hash_) {
2137 case Hash("urecpe_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002138 urecpe(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002139 break;
2140 case Hash("ursqrte_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002141 ursqrte(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002142 break;
2143 default:
2144 VIXL_UNIMPLEMENTED();
2145 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002146 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002147}
2148
2149void Simulator::Simulate_ZdS_ZnH_ZmH_imm(const Instruction* instr) {
2150 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong1719b712020-09-25 18:16:40 -07002151 SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
Martyn Capewell6bf28752020-08-05 11:57:06 +01002152 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong1719b712020-09-25 18:16:40 -07002153
2154 SimVRegister temp, zm_idx, zn_b, zn_t;
2155 // Instead of calling the indexed form of the instruction logic, we call the
2156 // vector form, which can reuse existing function logics without modification.
Martyn Capewell97ca8062020-10-23 14:45:14 +01002157 // Select the specified elements based on the index input and than pack them
2158 // to
TatWai Chong1719b712020-09-25 18:16:40 -07002159 // the corresponding position.
2160 Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
2161 dup_elements_to_segments(kFormatVnH, temp, zm, index);
2162 pack_even_elements(kFormatVnH, zm_idx, temp);
2163
2164 pack_even_elements(kFormatVnH, zn_b, zn);
2165 pack_odd_elements(kFormatVnH, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002166
2167 switch (form_hash_) {
2168 case Hash("smullb_z_zzi_s"):
2169 VIXL_UNIMPLEMENTED();
2170 break;
2171 case Hash("smullt_z_zzi_s"):
2172 VIXL_UNIMPLEMENTED();
2173 break;
2174 case Hash("sqdmullb_z_zzi_s"):
TatWai Chong1719b712020-09-25 18:16:40 -07002175 sqdmull(kFormatVnS, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002176 break;
2177 case Hash("sqdmullt_z_zzi_s"):
TatWai Chong1719b712020-09-25 18:16:40 -07002178 sqdmull(kFormatVnS, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002179 break;
2180 case Hash("umullb_z_zzi_s"):
2181 VIXL_UNIMPLEMENTED();
2182 break;
2183 case Hash("umullt_z_zzi_s"):
2184 VIXL_UNIMPLEMENTED();
2185 break;
2186 default:
2187 VIXL_UNIMPLEMENTED();
2188 }
2189}
2190
2191void Simulator::Simulate_ZdS_ZnS_ZmS_imm(const Instruction* instr) {
2192 SimVRegister& zd = ReadVRegister(instr->GetRd());
2193 USE(zd);
2194 SimVRegister& zn = ReadVRegister(instr->GetRn());
2195 USE(zn);
2196
2197 switch (form_hash_) {
2198 case Hash("mul_z_zzi_s"):
2199 VIXL_UNIMPLEMENTED();
2200 break;
2201 case Hash("sqdmulh_z_zzi_s"):
2202 VIXL_UNIMPLEMENTED();
2203 break;
2204 case Hash("sqrdmulh_z_zzi_s"):
2205 VIXL_UNIMPLEMENTED();
2206 break;
2207 default:
2208 VIXL_UNIMPLEMENTED();
2209 }
2210}
2211
2212void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002213 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002214 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002215 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002216 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002217 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002218
2219 switch (form_hash_) {
2220 case Hash("flogb_z_p_z"):
2221 VIXL_UNIMPLEMENTED();
2222 break;
2223 case Hash("sqabs_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002224 abs(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002225 break;
2226 case Hash("sqneg_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002227 neg(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002228 break;
2229 default:
2230 VIXL_UNIMPLEMENTED();
2231 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002232 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002233}
2234
2235void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell030875c2020-10-21 18:08:05 +01002236 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002237 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002238 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002239 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002240 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell030875c2020-10-21 18:08:05 +01002241 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002242
Martyn Capewell030875c2020-10-21 18:08:05 +01002243 VIXL_ASSERT(form_hash_ == Hash("histcnt_z_p_zz"));
2244 if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
Martyn Capewell710ec6f2020-10-22 16:56:17 +01002245 histogram(vform, result, pg, zn, zm);
Martyn Capewell030875c2020-10-21 18:08:05 +01002246 mov_zeroing(vform, zd, pg, result);
2247 } else {
2248 VIXL_UNIMPLEMENTED();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002249 }
2250}
2251
2252void Simulator::Simulate_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr) {
2253 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2254 USE(pg);
2255 SimVRegister& zd = ReadVRegister(instr->GetRd());
2256 USE(zd);
2257 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
2258 USE(zn1);
2259
2260 switch (form_hash_) {
2261 case Hash("splice_z_p_zz_con"):
2262 VIXL_UNIMPLEMENTED();
2263 break;
2264 default:
2265 VIXL_UNIMPLEMENTED();
2266 }
2267}
2268
Martyn Capewell6bf28752020-08-05 11:57:06 +01002269void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002270 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002271 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002272 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002273 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002274 SimVRegister result;
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002275 bool do_bext = false;
2276
Martyn Capewell6bf28752020-08-05 11:57:06 +01002277 switch (form_hash_) {
2278 case Hash("bdep_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002279 bdep(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002280 break;
2281 case Hash("bext_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002282 do_bext = true;
2283 VIXL_FALLTHROUGH();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002284 case Hash("bgrp_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002285 bgrp(vform, zd, zn, zm, do_bext);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002286 break;
2287 case Hash("eorbt_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002288 rotate_elements_right(vform, result, zm, 1);
2289 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2290 mov_alternating(vform, zd, result, 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002291 break;
2292 case Hash("eortb_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002293 rotate_elements_right(vform, result, zm, -1);
2294 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2295 mov_alternating(vform, zd, result, 1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002296 break;
2297 case Hash("mul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002298 mul(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002299 break;
2300 case Hash("smulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002301 smulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002302 break;
2303 case Hash("sqdmulh_z_zz"):
2304 VIXL_UNIMPLEMENTED();
2305 break;
2306 case Hash("sqrdmulh_z_zz"):
2307 VIXL_UNIMPLEMENTED();
2308 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002309 case Hash("umulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002310 umulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002311 break;
2312 default:
2313 VIXL_UNIMPLEMENTED();
2314 }
2315}
2316
2317void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002318 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002319 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002320 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002321 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002322
2323 SimVRegister zm_b, zm_t;
TatWai Chong236e7ae2020-09-13 14:55:04 -07002324 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2325 pack_even_elements(vform_half, zm_b, zm);
2326 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002327
2328 switch (form_hash_) {
2329 case Hash("saddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002330 saddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002331 break;
2332 case Hash("saddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002333 saddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002334 break;
2335 case Hash("ssubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002336 ssubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002337 break;
2338 case Hash("ssubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002339 ssubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002340 break;
2341 case Hash("uaddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002342 uaddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002343 break;
2344 case Hash("uaddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002345 uaddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002346 break;
2347 case Hash("usubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002348 usubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002349 break;
2350 case Hash("usubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002351 usubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002352 break;
2353 default:
2354 VIXL_UNIMPLEMENTED();
2355 }
2356}
2357
2358void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2359 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002360 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell78743b62020-09-09 11:08:57 +01002361
2362 std::pair<int, int> shift_and_lane_size =
2363 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2364 int lane_size = shift_and_lane_size.second;
2365 VIXL_ASSERT((lane_size >= 0) &&
2366 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2367 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2368 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002369
2370 switch (form_hash_) {
2371 case Hash("sli_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002372 // Shift distance is computed differently for left shifts. Convert the
2373 // result.
2374 shift_dist = (8 << lane_size) - shift_dist;
2375 sli(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002376 break;
2377 case Hash("sri_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002378 sri(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002379 break;
2380 default:
2381 VIXL_UNIMPLEMENTED();
2382 }
2383}
2384
Martyn Capewellea9b4072020-10-09 11:25:26 +01002385void Simulator::SimulateSVENarrow(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002386 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002387 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellb5636e52020-09-17 11:21:29 +01002388 SimVRegister result;
2389
2390 std::pair<int, int> shift_and_lane_size =
2391 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2392 int lane_size = shift_and_lane_size.second;
2393 VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2394 (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2395 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewellea9b4072020-10-09 11:25:26 +01002396 int right_shift_dist = shift_and_lane_size.first;
Martyn Capewellb5636e52020-09-17 11:21:29 +01002397 bool top = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002398
2399 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002400 case Hash("sqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002401 top = true;
2402 VIXL_FALLTHROUGH();
2403 case Hash("sqxtnb_z_zz"):
2404 sqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002405 break;
2406 case Hash("sqxtunt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002407 top = true;
2408 VIXL_FALLTHROUGH();
2409 case Hash("sqxtunb_z_zz"):
2410 sqxtun(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002411 break;
2412 case Hash("uqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002413 top = true;
2414 VIXL_FALLTHROUGH();
2415 case Hash("uqxtnb_z_zz"):
2416 uqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002417 break;
Martyn Capewellea9b4072020-10-09 11:25:26 +01002418 case Hash("rshrnt_z_zi"):
2419 top = true;
2420 VIXL_FALLTHROUGH();
2421 case Hash("rshrnb_z_zi"):
2422 rshrn(vform, result, zn, right_shift_dist);
2423 break;
2424 case Hash("shrnt_z_zi"):
2425 top = true;
2426 VIXL_FALLTHROUGH();
2427 case Hash("shrnb_z_zi"):
2428 shrn(vform, result, zn, right_shift_dist);
2429 break;
2430 case Hash("sqrshrnt_z_zi"):
2431 top = true;
2432 VIXL_FALLTHROUGH();
2433 case Hash("sqrshrnb_z_zi"):
2434 sqrshrn(vform, result, zn, right_shift_dist);
2435 break;
2436 case Hash("sqrshrunt_z_zi"):
2437 top = true;
2438 VIXL_FALLTHROUGH();
2439 case Hash("sqrshrunb_z_zi"):
2440 sqrshrun(vform, result, zn, right_shift_dist);
2441 break;
2442 case Hash("sqshrnt_z_zi"):
2443 top = true;
2444 VIXL_FALLTHROUGH();
2445 case Hash("sqshrnb_z_zi"):
2446 sqshrn(vform, result, zn, right_shift_dist);
2447 break;
2448 case Hash("sqshrunt_z_zi"):
2449 top = true;
2450 VIXL_FALLTHROUGH();
2451 case Hash("sqshrunb_z_zi"):
2452 sqshrun(vform, result, zn, right_shift_dist);
2453 break;
2454 case Hash("uqrshrnt_z_zi"):
2455 top = true;
2456 VIXL_FALLTHROUGH();
2457 case Hash("uqrshrnb_z_zi"):
2458 uqrshrn(vform, result, zn, right_shift_dist);
2459 break;
2460 case Hash("uqshrnt_z_zi"):
2461 top = true;
2462 VIXL_FALLTHROUGH();
2463 case Hash("uqshrnb_z_zi"):
2464 uqshrn(vform, result, zn, right_shift_dist);
2465 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002466 default:
2467 VIXL_UNIMPLEMENTED();
2468 }
Martyn Capewellb5636e52020-09-17 11:21:29 +01002469
2470 if (top) {
2471 // Keep even elements, replace odd elements with the results.
2472 xtn(vform, zd, zd);
2473 zip1(vform, zd, zd, result);
2474 } else {
2475 // Zero odd elements, replace even elements with the results.
2476 SimVRegister zero;
2477 zero.Clear();
2478 zip1(vform, zd, result, zero);
2479 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002480}
2481
Martyn Capewellc7275e62020-09-24 14:06:07 +01002482void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
Martyn Capewella2d7fbb2020-09-18 18:22:54 +01002483 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002484 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002485 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002486 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002487 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2488
2489 // Construct temporary registers containing the even (bottom) and odd (top)
2490 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002491 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2492 pack_even_elements(vform_half, zn_b, zn);
2493 pack_even_elements(vform_half, zm_b, zm);
2494 pack_odd_elements(vform_half, zn_t, zn);
2495 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewellc7275e62020-09-24 14:06:07 +01002496
2497 switch (form_hash_) {
2498 case Hash("sabdlb_z_zz"):
2499 sabdl(vform, zd, zn_b, zm_b);
2500 break;
2501 case Hash("sabdlt_z_zz"):
2502 sabdl(vform, zd, zn_t, zm_t);
2503 break;
2504 case Hash("saddlb_z_zz"):
2505 saddl(vform, zd, zn_b, zm_b);
2506 break;
2507 case Hash("saddlbt_z_zz"):
2508 saddl(vform, zd, zn_b, zm_t);
2509 break;
2510 case Hash("saddlt_z_zz"):
2511 saddl(vform, zd, zn_t, zm_t);
2512 break;
2513 case Hash("ssublb_z_zz"):
2514 ssubl(vform, zd, zn_b, zm_b);
2515 break;
2516 case Hash("ssublbt_z_zz"):
2517 ssubl(vform, zd, zn_b, zm_t);
2518 break;
2519 case Hash("ssublt_z_zz"):
2520 ssubl(vform, zd, zn_t, zm_t);
2521 break;
2522 case Hash("ssubltb_z_zz"):
2523 ssubl(vform, zd, zn_t, zm_b);
2524 break;
2525 case Hash("uabdlb_z_zz"):
2526 uabdl(vform, zd, zn_b, zm_b);
2527 break;
2528 case Hash("uabdlt_z_zz"):
2529 uabdl(vform, zd, zn_t, zm_t);
2530 break;
2531 case Hash("uaddlb_z_zz"):
2532 uaddl(vform, zd, zn_b, zm_b);
2533 break;
2534 case Hash("uaddlt_z_zz"):
2535 uaddl(vform, zd, zn_t, zm_t);
2536 break;
2537 case Hash("usublb_z_zz"):
2538 usubl(vform, zd, zn_b, zm_b);
2539 break;
2540 case Hash("usublt_z_zz"):
2541 usubl(vform, zd, zn_t, zm_t);
2542 break;
Martyn Capewell67d2f822020-10-13 16:39:33 +01002543 case Hash("sabalb_z_zzz"):
2544 sabal(vform, zd, zn_b, zm_b);
2545 break;
2546 case Hash("sabalt_z_zzz"):
2547 sabal(vform, zd, zn_t, zm_t);
2548 break;
2549 case Hash("uabalb_z_zzz"):
2550 uabal(vform, zd, zn_b, zm_b);
2551 break;
2552 case Hash("uabalt_z_zzz"):
2553 uabal(vform, zd, zn_t, zm_t);
2554 break;
Martyn Capewellc7275e62020-09-24 14:06:07 +01002555 default:
2556 VIXL_UNIMPLEMENTED();
2557 }
2558}
2559
TatWai Chong236e7ae2020-09-13 14:55:04 -07002560void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2561 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewellc7275e62020-09-24 14:06:07 +01002562 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002563 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002564 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong236e7ae2020-09-13 14:55:04 -07002565 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2566 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2567 pack_even_elements(vform_half, zn_b, zn);
2568 pack_even_elements(vform_half, zm_b, zm);
2569 pack_odd_elements(vform_half, zn_t, zn);
2570 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002571
2572 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002573 case Hash("pmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002574 // '00' is reserved for Q-sized lane.
2575 if (vform == kFormatVnB) {
2576 VIXL_UNIMPLEMENTED();
2577 }
2578 pmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002579 break;
2580 case Hash("pmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002581 // '00' is reserved for Q-sized lane.
2582 if (vform == kFormatVnB) {
2583 VIXL_UNIMPLEMENTED();
2584 }
2585 pmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002586 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002587 case Hash("smullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002588 smull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002589 break;
2590 case Hash("smullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002591 smull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002592 break;
2593 case Hash("sqdmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002594 sqdmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002595 break;
2596 case Hash("sqdmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002597 sqdmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002598 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002599 case Hash("umullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002600 umull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002601 break;
2602 case Hash("umullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002603 umull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002604 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002605 default:
2606 VIXL_UNIMPLEMENTED();
2607 }
2608}
2609
Martyn Capewell8b9c44b2020-10-14 18:21:42 +01002610void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2611 SimVRegister& zd = ReadVRegister(instr->GetRd());
2612 SimVRegister& zm = ReadVRegister(instr->GetRm());
2613 SimVRegister& zn = ReadVRegister(instr->GetRn());
2614 SimVRegister result;
2615 bool top = false;
2616
2617 VectorFormat vform_src = instr->GetSVEVectorFormat();
2618 if (vform_src == kFormatVnB) {
2619 VIXL_UNIMPLEMENTED();
2620 }
2621 VectorFormat vform = VectorFormatHalfWidth(vform_src);
2622
2623 switch (form_hash_) {
2624 case Hash("addhnt_z_zz"):
2625 top = true;
2626 VIXL_FALLTHROUGH();
2627 case Hash("addhnb_z_zz"):
2628 addhn(vform, result, zn, zm);
2629 break;
2630 case Hash("raddhnt_z_zz"):
2631 top = true;
2632 VIXL_FALLTHROUGH();
2633 case Hash("raddhnb_z_zz"):
2634 raddhn(vform, result, zn, zm);
2635 break;
2636 case Hash("rsubhnt_z_zz"):
2637 top = true;
2638 VIXL_FALLTHROUGH();
2639 case Hash("rsubhnb_z_zz"):
2640 rsubhn(vform, result, zn, zm);
2641 break;
2642 case Hash("subhnt_z_zz"):
2643 top = true;
2644 VIXL_FALLTHROUGH();
2645 case Hash("subhnb_z_zz"):
2646 subhn(vform, result, zn, zm);
2647 break;
2648 default:
2649 VIXL_UNIMPLEMENTED();
2650 }
2651
2652 if (top) {
2653 // Keep even elements, replace odd elements with the results.
2654 xtn(vform, zd, zd);
2655 zip1(vform, zd, zd, result);
2656 } else {
2657 // Zero odd elements, replace even elements with the results.
2658 SimVRegister zero;
2659 zero.Clear();
2660 zip1(vform, zd, result, zero);
2661 }
2662}
2663
Martyn Capewellea9b4072020-10-09 11:25:26 +01002664void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002665 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002666 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell51dcef92020-10-08 16:04:12 +01002667 SimVRegister zn_b, zn_t;
2668
2669 std::pair<int, int> shift_and_lane_size =
2670 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2671 int lane_size = shift_and_lane_size.second;
2672 VIXL_ASSERT((lane_size >= 0) &&
2673 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2674 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2675 int right_shift_dist = shift_and_lane_size.first;
2676 int left_shift_dist = (8 << lane_size) - right_shift_dist;
2677
2678 // Construct temporary registers containing the even (bottom) and odd (top)
2679 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002680 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2681 pack_even_elements(vform_half, zn_b, zn);
2682 pack_odd_elements(vform_half, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002683
2684 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002685 case Hash("sshllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002686 sshll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002687 break;
2688 case Hash("sshllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002689 sshll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002690 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002691 case Hash("ushllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002692 ushll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002693 break;
2694 case Hash("ushllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002695 ushll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002696 break;
2697 default:
2698 VIXL_UNIMPLEMENTED();
2699 }
2700}
2701
2702void Simulator::Simulate_ZdaD_ZnD_ZmD_imm(const Instruction* instr) {
2703 SimVRegister& zda = ReadVRegister(instr->GetRd());
2704 USE(zda);
2705 SimVRegister& zn = ReadVRegister(instr->GetRn());
2706 USE(zn);
2707
2708 switch (form_hash_) {
2709 case Hash("mla_z_zzzi_d"):
2710 VIXL_UNIMPLEMENTED();
2711 break;
2712 case Hash("mls_z_zzzi_d"):
2713 VIXL_UNIMPLEMENTED();
2714 break;
2715 case Hash("sqrdmlah_z_zzzi_d"):
2716 VIXL_UNIMPLEMENTED();
2717 break;
2718 case Hash("sqrdmlsh_z_zzzi_d"):
2719 VIXL_UNIMPLEMENTED();
2720 break;
2721 default:
2722 VIXL_UNIMPLEMENTED();
2723 }
2724}
2725
Martyn Capewell6bf28752020-08-05 11:57:06 +01002726void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2727 SimVRegister& zda = ReadVRegister(instr->GetRd());
2728 USE(zda);
2729 SimVRegister& zn = ReadVRegister(instr->GetRn());
2730 USE(zn);
2731
2732 switch (form_hash_) {
2733 case Hash("smlalb_z_zzzi_d"):
2734 VIXL_UNIMPLEMENTED();
2735 break;
2736 case Hash("smlalt_z_zzzi_d"):
2737 VIXL_UNIMPLEMENTED();
2738 break;
2739 case Hash("smlslb_z_zzzi_d"):
2740 VIXL_UNIMPLEMENTED();
2741 break;
2742 case Hash("smlslt_z_zzzi_d"):
2743 VIXL_UNIMPLEMENTED();
2744 break;
2745 case Hash("sqdmlalb_z_zzzi_d"):
2746 VIXL_UNIMPLEMENTED();
2747 break;
2748 case Hash("sqdmlalt_z_zzzi_d"):
2749 VIXL_UNIMPLEMENTED();
2750 break;
2751 case Hash("sqdmlslb_z_zzzi_d"):
2752 VIXL_UNIMPLEMENTED();
2753 break;
2754 case Hash("sqdmlslt_z_zzzi_d"):
2755 VIXL_UNIMPLEMENTED();
2756 break;
2757 case Hash("umlalb_z_zzzi_d"):
2758 VIXL_UNIMPLEMENTED();
2759 break;
2760 case Hash("umlalt_z_zzzi_d"):
2761 VIXL_UNIMPLEMENTED();
2762 break;
2763 case Hash("umlslb_z_zzzi_d"):
2764 VIXL_UNIMPLEMENTED();
2765 break;
2766 case Hash("umlslt_z_zzzi_d"):
2767 VIXL_UNIMPLEMENTED();
2768 break;
2769 default:
2770 VIXL_UNIMPLEMENTED();
2771 }
2772}
2773
2774void Simulator::Simulate_ZdaH_ZnH_ZmH_imm(const Instruction* instr) {
2775 SimVRegister& zda = ReadVRegister(instr->GetRd());
2776 USE(zda);
2777 SimVRegister& zn = ReadVRegister(instr->GetRn());
2778 USE(zn);
2779
2780 switch (form_hash_) {
2781 case Hash("mla_z_zzzi_h"):
2782 VIXL_UNIMPLEMENTED();
2783 break;
2784 case Hash("mls_z_zzzi_h"):
2785 VIXL_UNIMPLEMENTED();
2786 break;
2787 case Hash("sqrdmlah_z_zzzi_h"):
2788 VIXL_UNIMPLEMENTED();
2789 break;
2790 case Hash("sqrdmlsh_z_zzzi_h"):
2791 VIXL_UNIMPLEMENTED();
2792 break;
2793 default:
2794 VIXL_UNIMPLEMENTED();
2795 }
2796}
2797
2798void Simulator::Simulate_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr) {
2799 SimVRegister& zda = ReadVRegister(instr->GetRd());
2800 USE(zda);
2801 SimVRegister& zn = ReadVRegister(instr->GetRn());
2802 USE(zn);
2803
2804 switch (form_hash_) {
2805 case Hash("cmla_z_zzzi_h"):
2806 VIXL_UNIMPLEMENTED();
2807 break;
2808 case Hash("sqrdcmlah_z_zzzi_h"):
2809 VIXL_UNIMPLEMENTED();
2810 break;
2811 default:
2812 VIXL_UNIMPLEMENTED();
2813 }
2814}
2815
Martyn Capewell6bf28752020-08-05 11:57:06 +01002816void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2817 SimVRegister& zda = ReadVRegister(instr->GetRd());
2818 USE(zda);
2819 SimVRegister& zm = ReadVRegister(instr->GetRm());
2820 USE(zm);
2821 SimVRegister& zn = ReadVRegister(instr->GetRn());
2822 USE(zn);
2823
2824 switch (form_hash_) {
2825 case Hash("fmlalb_z_zzz"):
2826 VIXL_UNIMPLEMENTED();
2827 break;
2828 case Hash("fmlalt_z_zzz"):
2829 VIXL_UNIMPLEMENTED();
2830 break;
2831 case Hash("fmlslb_z_zzz"):
2832 VIXL_UNIMPLEMENTED();
2833 break;
2834 case Hash("fmlslt_z_zzz"):
2835 VIXL_UNIMPLEMENTED();
2836 break;
2837 default:
2838 VIXL_UNIMPLEMENTED();
2839 }
2840}
2841
2842void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2843 SimVRegister& zda = ReadVRegister(instr->GetRd());
2844 USE(zda);
2845 SimVRegister& zm = ReadVRegister(instr->GetRm());
2846 USE(zm);
2847 SimVRegister& zn = ReadVRegister(instr->GetRn());
2848 USE(zn);
2849
2850 switch (form_hash_) {
2851 case Hash("fmlalb_z_zzzi_s"):
2852 VIXL_UNIMPLEMENTED();
2853 break;
2854 case Hash("fmlalt_z_zzzi_s"):
2855 VIXL_UNIMPLEMENTED();
2856 break;
2857 case Hash("fmlslb_z_zzzi_s"):
2858 VIXL_UNIMPLEMENTED();
2859 break;
2860 case Hash("fmlslt_z_zzzi_s"):
2861 VIXL_UNIMPLEMENTED();
2862 break;
2863 case Hash("smlalb_z_zzzi_s"):
2864 VIXL_UNIMPLEMENTED();
2865 break;
2866 case Hash("smlalt_z_zzzi_s"):
2867 VIXL_UNIMPLEMENTED();
2868 break;
2869 case Hash("smlslb_z_zzzi_s"):
2870 VIXL_UNIMPLEMENTED();
2871 break;
2872 case Hash("smlslt_z_zzzi_s"):
2873 VIXL_UNIMPLEMENTED();
2874 break;
2875 case Hash("sqdmlalb_z_zzzi_s"):
2876 VIXL_UNIMPLEMENTED();
2877 break;
2878 case Hash("sqdmlalt_z_zzzi_s"):
2879 VIXL_UNIMPLEMENTED();
2880 break;
2881 case Hash("sqdmlslb_z_zzzi_s"):
2882 VIXL_UNIMPLEMENTED();
2883 break;
2884 case Hash("sqdmlslt_z_zzzi_s"):
2885 VIXL_UNIMPLEMENTED();
2886 break;
2887 case Hash("umlalb_z_zzzi_s"):
2888 VIXL_UNIMPLEMENTED();
2889 break;
2890 case Hash("umlalt_z_zzzi_s"):
2891 VIXL_UNIMPLEMENTED();
2892 break;
2893 case Hash("umlslb_z_zzzi_s"):
2894 VIXL_UNIMPLEMENTED();
2895 break;
2896 case Hash("umlslt_z_zzzi_s"):
2897 VIXL_UNIMPLEMENTED();
2898 break;
2899 default:
2900 VIXL_UNIMPLEMENTED();
2901 }
2902}
2903
2904void Simulator::Simulate_ZdaS_ZnS_ZmS_imm(const Instruction* instr) {
2905 SimVRegister& zda = ReadVRegister(instr->GetRd());
2906 USE(zda);
2907 SimVRegister& zn = ReadVRegister(instr->GetRn());
2908 USE(zn);
2909
2910 switch (form_hash_) {
2911 case Hash("mla_z_zzzi_s"):
2912 VIXL_UNIMPLEMENTED();
2913 break;
2914 case Hash("mls_z_zzzi_s"):
2915 VIXL_UNIMPLEMENTED();
2916 break;
2917 case Hash("sqrdmlah_z_zzzi_s"):
2918 VIXL_UNIMPLEMENTED();
2919 break;
2920 case Hash("sqrdmlsh_z_zzzi_s"):
2921 VIXL_UNIMPLEMENTED();
2922 break;
2923 default:
2924 VIXL_UNIMPLEMENTED();
2925 }
2926}
2927
2928void Simulator::Simulate_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr) {
2929 SimVRegister& zda = ReadVRegister(instr->GetRd());
2930 USE(zda);
2931 SimVRegister& zn = ReadVRegister(instr->GetRn());
2932 USE(zn);
2933
2934 switch (form_hash_) {
2935 case Hash("cmla_z_zzzi_s"):
2936 VIXL_UNIMPLEMENTED();
2937 break;
2938 case Hash("sqrdcmlah_z_zzzi_s"):
2939 VIXL_UNIMPLEMENTED();
2940 break;
2941 default:
2942 VIXL_UNIMPLEMENTED();
2943 }
2944}
2945
2946void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
TatWai Chong602aa122020-10-05 16:28:27 -07002947 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002948 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002949 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002950 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong602aa122020-10-05 16:28:27 -07002951 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002952
2953 switch (form_hash_) {
2954 case Hash("sadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002955 sadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002956 break;
2957 case Hash("uadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002958 uadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002959 break;
2960 default:
2961 VIXL_UNIMPLEMENTED();
2962 }
TatWai Chong602aa122020-10-05 16:28:27 -07002963 mov_merging(vform, zda, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002964}
2965
Martyn Capewellc4b56bb2020-10-14 15:45:14 +01002966void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
2967 VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
2968 SimVRegister& zda = ReadVRegister(instr->GetRd());
2969 SimVRegister& zm = ReadVRegister(instr->GetRm());
2970 SimVRegister& zn = ReadVRegister(instr->GetRn());
2971
2972 SimVRegister not_zn;
2973 not_(vform, not_zn, zn);
2974
2975 switch (form_hash_) {
2976 case Hash("adclb_z_zzz"):
2977 adcl(vform, zda, zn, zm, /* top = */ false);
2978 break;
2979 case Hash("adclt_z_zzz"):
2980 adcl(vform, zda, zn, zm, /* top = */ true);
2981 break;
2982 case Hash("sbclb_z_zzz"):
2983 adcl(vform, zda, not_zn, zm, /* top = */ false);
2984 break;
2985 case Hash("sbclt_z_zzz"):
2986 adcl(vform, zda, not_zn, zm, /* top = */ true);
2987 break;
2988 default:
2989 VIXL_UNIMPLEMENTED();
2990 }
2991}
2992
Martyn Capewell6bf28752020-08-05 11:57:06 +01002993void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002994 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002995 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002996 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002997 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002998
2999 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003000 case Hash("saba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01003001 saba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003002 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003003 case Hash("sqrdmlah_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07003004 sqrdmlah(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003005 break;
3006 case Hash("sqrdmlsh_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07003007 sqrdmlsh(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003008 break;
3009 case Hash("uaba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01003010 uaba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003011 break;
3012 default:
3013 VIXL_UNIMPLEMENTED();
3014 }
3015}
3016
3017void Simulator::Simulate_ZdaT_ZnT_ZmT_const(const Instruction* instr) {
3018 SimVRegister& zda = ReadVRegister(instr->GetRd());
3019 USE(zda);
3020 SimVRegister& zm = ReadVRegister(instr->GetRm());
3021 USE(zm);
3022 SimVRegister& zn = ReadVRegister(instr->GetRn());
3023 USE(zn);
3024
3025 switch (form_hash_) {
3026 case Hash("cmla_z_zzz"):
3027 VIXL_UNIMPLEMENTED();
3028 break;
3029 case Hash("sqrdcmlah_z_zzz"):
3030 VIXL_UNIMPLEMENTED();
3031 break;
3032 default:
3033 VIXL_UNIMPLEMENTED();
3034 }
3035}
3036
3037void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003038 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003039 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003040
3041 std::pair<int, int> shift_and_lane_size =
3042 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3043 int lane_size = shift_and_lane_size.second;
3044 VIXL_ASSERT((lane_size >= 0) &&
3045 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3046 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3047 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003048
3049 switch (form_hash_) {
3050 case Hash("srsra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003051 srsra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003052 break;
3053 case Hash("ssra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003054 ssra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003055 break;
3056 case Hash("ursra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003057 ursra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003058 break;
3059 case Hash("usra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003060 usra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003061 break;
3062 default:
3063 VIXL_UNIMPLEMENTED();
3064 }
3065}
3066
3067void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
3068 SimVRegister& zda = ReadVRegister(instr->GetRd());
3069 USE(zda);
3070 SimVRegister& zm = ReadVRegister(instr->GetRm());
3071 USE(zm);
3072 SimVRegister& zn = ReadVRegister(instr->GetRn());
3073 USE(zn);
3074
3075 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003076 case Hash("smlalb_z_zzz"):
3077 VIXL_UNIMPLEMENTED();
3078 break;
3079 case Hash("smlalt_z_zzz"):
3080 VIXL_UNIMPLEMENTED();
3081 break;
3082 case Hash("smlslb_z_zzz"):
3083 VIXL_UNIMPLEMENTED();
3084 break;
3085 case Hash("smlslt_z_zzz"):
3086 VIXL_UNIMPLEMENTED();
3087 break;
3088 case Hash("sqdmlalb_z_zzz"):
3089 VIXL_UNIMPLEMENTED();
3090 break;
3091 case Hash("sqdmlalbt_z_zzz"):
3092 VIXL_UNIMPLEMENTED();
3093 break;
3094 case Hash("sqdmlalt_z_zzz"):
3095 VIXL_UNIMPLEMENTED();
3096 break;
3097 case Hash("sqdmlslb_z_zzz"):
3098 VIXL_UNIMPLEMENTED();
3099 break;
3100 case Hash("sqdmlslbt_z_zzz"):
3101 VIXL_UNIMPLEMENTED();
3102 break;
3103 case Hash("sqdmlslt_z_zzz"):
3104 VIXL_UNIMPLEMENTED();
3105 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003106 case Hash("umlalb_z_zzz"):
3107 VIXL_UNIMPLEMENTED();
3108 break;
3109 case Hash("umlalt_z_zzz"):
3110 VIXL_UNIMPLEMENTED();
3111 break;
3112 case Hash("umlslb_z_zzz"):
3113 VIXL_UNIMPLEMENTED();
3114 break;
3115 case Hash("umlslt_z_zzz"):
3116 VIXL_UNIMPLEMENTED();
3117 break;
3118 default:
3119 VIXL_UNIMPLEMENTED();
3120 }
3121}
3122
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003123void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
Martyn Capewellf4da2202020-11-03 17:42:57 +00003124 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003125 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003126 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellf4da2202020-11-03 17:42:57 +00003127 int rot = instr->ExtractBits(11, 10) * 90;
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003128 unsigned zm_code = instr->GetRm();
3129 int index = -1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003130
3131 switch (form_hash_) {
3132 case Hash("cdot_z_zzz"):
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003133 // Nothing to do.
3134 break;
3135 case Hash("cdot_z_zzzi_s"):
3136 index = zm_code >> 3;
3137 zm_code &= 0x7;
3138 break;
3139 case Hash("cdot_z_zzzi_d"):
3140 index = zm_code >> 4;
3141 zm_code &= 0xf;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003142 break;
3143 default:
3144 VIXL_UNIMPLEMENTED();
3145 }
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003146
3147 SimVRegister temp;
3148 SimVRegister& zm = ReadVRegister(zm_code);
3149 if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3150 cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003151}
3152
Martyn Capewellb1b95782020-10-23 15:59:49 +01003153void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3154 VectorFormat vform = kFormatVnD;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003155 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003156 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellb1b95782020-10-23 15:59:49 +01003157 SimVRegister& zk = ReadVRegister(instr->GetRn());
3158 SimVRegister temp;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003159
3160 switch (form_hash_) {
3161 case Hash("bcax_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003162 bic(vform, temp, zm, zk);
3163 eor(vform, zdn, temp, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003164 break;
3165 case Hash("bsl1n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003166 not_(vform, temp, zdn);
3167 bsl(vform, zdn, zk, temp, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003168 break;
3169 case Hash("bsl2n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003170 not_(vform, temp, zm);
3171 bsl(vform, zdn, zk, zdn, temp);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003172 break;
3173 case Hash("bsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003174 bsl(vform, zdn, zk, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003175 break;
3176 case Hash("eor3_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003177 eor(vform, temp, zdn, zm);
3178 eor(vform, zdn, temp, zk);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003179 break;
3180 case Hash("nbsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003181 bsl(vform, zdn, zk, zdn, zm);
3182 not_(vform, zdn, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003183 break;
3184 default:
3185 VIXL_UNIMPLEMENTED();
3186 }
3187}
3188
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003189void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3190 VectorFormat vform = instr->GetSVEVectorFormat();
3191 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3192 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3193 SimVRegister& zm = ReadVRegister(instr->GetRn());
3194 SimVRegister result;
3195
3196 switch (form_hash_) {
3197 case Hash("shadd_z_p_zz"):
3198 add(vform, result, zdn, zm).Halve(vform);
3199 break;
3200 case Hash("shsub_z_p_zz"):
3201 sub(vform, result, zdn, zm).Halve(vform);
3202 break;
3203 case Hash("shsubr_z_p_zz"):
3204 sub(vform, result, zm, zdn).Halve(vform);
3205 break;
3206 case Hash("srhadd_z_p_zz"):
3207 add(vform, result, zdn, zm).Halve(vform).Round(vform);
3208 break;
3209 case Hash("uhadd_z_p_zz"):
3210 add(vform, result, zdn, zm).Uhalve(vform);
3211 break;
3212 case Hash("uhsub_z_p_zz"):
3213 sub(vform, result, zdn, zm).Uhalve(vform);
3214 break;
3215 case Hash("uhsubr_z_p_zz"):
3216 sub(vform, result, zm, zdn).Uhalve(vform);
3217 break;
3218 case Hash("urhadd_z_p_zz"):
3219 add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3220 break;
3221 default:
3222 VIXL_UNIMPLEMENTED();
Martyn Capewell9b532192020-09-15 16:20:11 +01003223 break;
3224 }
3225 mov_merging(vform, zdn, pg, result);
3226}
3227
3228void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3229 VectorFormat vform = instr->GetSVEVectorFormat();
3230 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3231 SimVRegister& zm = ReadVRegister(instr->GetRn());
3232 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3233 SimVRegister result;
3234
3235 switch (form_hash_) {
3236 case Hash("sqadd_z_p_zz"):
3237 add(vform, result, zdn, zm).SignedSaturate(vform);
3238 break;
3239 case Hash("sqsub_z_p_zz"):
3240 sub(vform, result, zdn, zm).SignedSaturate(vform);
3241 break;
3242 case Hash("sqsubr_z_p_zz"):
3243 sub(vform, result, zm, zdn).SignedSaturate(vform);
3244 break;
3245 case Hash("suqadd_z_p_zz"):
3246 suqadd(vform, result, zdn, zm);
3247 break;
3248 case Hash("uqadd_z_p_zz"):
3249 add(vform, result, zdn, zm).UnsignedSaturate(vform);
3250 break;
3251 case Hash("uqsub_z_p_zz"):
3252 sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3253 break;
3254 case Hash("uqsubr_z_p_zz"):
3255 sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3256 break;
3257 case Hash("usqadd_z_p_zz"):
3258 usqadd(vform, result, zdn, zm);
3259 break;
3260 default:
3261 VIXL_UNIMPLEMENTED();
3262 break;
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003263 }
3264 mov_merging(vform, zdn, pg, result);
3265}
3266
Martyn Capewellfa1e2112020-09-16 16:53:09 +01003267void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3268 VectorFormat vform = instr->GetSVEVectorFormat();
3269 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3270 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3271 SimVRegister& zm = ReadVRegister(instr->GetRn());
3272 SimVRegister result;
3273
3274 switch (form_hash_) {
3275 case Hash("addp_z_p_zz"):
3276 addp(vform, result, zdn, zm);
3277 break;
3278 case Hash("smaxp_z_p_zz"):
3279 smaxp(vform, result, zdn, zm);
3280 break;
3281 case Hash("sminp_z_p_zz"):
3282 sminp(vform, result, zdn, zm);
3283 break;
3284 case Hash("umaxp_z_p_zz"):
3285 umaxp(vform, result, zdn, zm);
3286 break;
3287 case Hash("uminp_z_p_zz"):
3288 uminp(vform, result, zdn, zm);
3289 break;
3290 default:
3291 VIXL_UNIMPLEMENTED();
3292 break;
3293 }
3294 mov_merging(vform, zdn, pg, result);
3295}
3296
Martyn Capewell6bf28752020-08-05 11:57:06 +01003297void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3298 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3299 USE(pg);
3300 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3301 USE(zdn);
3302 SimVRegister& zm = ReadVRegister(instr->GetRn());
3303 USE(zm);
3304
3305 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003306 case Hash("faddp_z_p_zz"):
3307 VIXL_UNIMPLEMENTED();
3308 break;
3309 case Hash("fmaxnmp_z_p_zz"):
3310 VIXL_UNIMPLEMENTED();
3311 break;
3312 case Hash("fmaxp_z_p_zz"):
3313 VIXL_UNIMPLEMENTED();
3314 break;
3315 case Hash("fminnmp_z_p_zz"):
3316 VIXL_UNIMPLEMENTED();
3317 break;
3318 case Hash("fminp_z_p_zz"):
3319 VIXL_UNIMPLEMENTED();
3320 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003321 case Hash("sqrshl_z_p_zz"):
3322 VIXL_UNIMPLEMENTED();
3323 break;
3324 case Hash("sqrshlr_z_p_zz"):
3325 VIXL_UNIMPLEMENTED();
3326 break;
3327 case Hash("sqshl_z_p_zz"):
3328 VIXL_UNIMPLEMENTED();
3329 break;
3330 case Hash("sqshlr_z_p_zz"):
3331 VIXL_UNIMPLEMENTED();
3332 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003333 case Hash("srshl_z_p_zz"):
3334 VIXL_UNIMPLEMENTED();
3335 break;
3336 case Hash("srshlr_z_p_zz"):
3337 VIXL_UNIMPLEMENTED();
3338 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003339 case Hash("uqrshl_z_p_zz"):
3340 VIXL_UNIMPLEMENTED();
3341 break;
3342 case Hash("uqrshlr_z_p_zz"):
3343 VIXL_UNIMPLEMENTED();
3344 break;
3345 case Hash("uqshl_z_p_zz"):
3346 VIXL_UNIMPLEMENTED();
3347 break;
3348 case Hash("uqshlr_z_p_zz"):
3349 VIXL_UNIMPLEMENTED();
3350 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003351 case Hash("urshl_z_p_zz"):
3352 VIXL_UNIMPLEMENTED();
3353 break;
3354 case Hash("urshlr_z_p_zz"):
3355 VIXL_UNIMPLEMENTED();
3356 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003357 default:
3358 VIXL_UNIMPLEMENTED();
3359 }
3360}
3361
3362void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3363 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003364 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003365
3366 std::pair<int, int> shift_and_lane_size =
3367 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3368 unsigned lane_size = shift_and_lane_size.second;
3369 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3370 int right_shift_dist = shift_and_lane_size.first;
3371 int left_shift_dist = (8 << lane_size) - right_shift_dist;
3372 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003373
3374 switch (form_hash_) {
3375 case Hash("sqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003376 sqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003377 break;
3378 case Hash("sqshlu_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003379 sqshlu(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003380 break;
3381 case Hash("srshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003382 sshr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003383 break;
3384 case Hash("uqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003385 uqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003386 break;
3387 case Hash("urshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003388 ushr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003389 break;
3390 default:
3391 VIXL_UNIMPLEMENTED();
3392 }
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003393 mov_merging(vform, zdn, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003394}
3395
Martyn Capewell97ca8062020-10-23 14:45:14 +01003396void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3397 VIXL_ASSERT(form_hash_ == Hash("xar_z_zzi"));
3398
3399 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3400 SimVRegister& zm = ReadVRegister(instr->GetRn());
3401
3402 std::pair<int, int> shift_and_lane_size =
3403 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3404 unsigned lane_size = shift_and_lane_size.second;
3405 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3406 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3407 int shift_dist = shift_and_lane_size.first;
Martyn Capewellb1b95782020-10-23 15:59:49 +01003408 eor(vform, zdn, zdn, zm);
Martyn Capewell97ca8062020-10-23 14:45:14 +01003409 ror(vform, zdn, zdn, shift_dist);
3410}
3411
Martyn Capewell6bf28752020-08-05 11:57:06 +01003412void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
Martyn Capewell819dcf92020-10-20 16:07:09 +01003413 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003414 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003415 SimVRegister& zm = ReadVRegister(instr->GetRn());
Martyn Capewell819dcf92020-10-20 16:07:09 +01003416 int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003417
3418 switch (form_hash_) {
3419 case Hash("cadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003420 cadd(vform, zdn, zdn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003421 break;
3422 case Hash("sqcadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003423 cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003424 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003425 default:
3426 VIXL_UNIMPLEMENTED();
3427 }
3428}
3429
3430void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3431 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003432 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003433 uint64_t xm = ReadXRegister(instr->GetRm());
3434
3435 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3436 int msize = -1;
3437 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003438
3439 switch (form_hash_) {
3440 case Hash("ldnt1b_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003441 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003442 break;
3443 case Hash("ldnt1d_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003444 msize = 3;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003445 break;
3446 case Hash("ldnt1h_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003447 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003448 break;
3449 case Hash("ldnt1sb_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003450 msize = 0;
3451 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003452 break;
3453 case Hash("ldnt1sh_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003454 msize = 1;
3455 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003456 break;
3457 case Hash("ldnt1sw_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003458 msize = 2;
3459 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003460 break;
3461 case Hash("ldnt1w_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003462 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003463 break;
3464 default:
3465 VIXL_UNIMPLEMENTED();
3466 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003467 addr.SetMsizeInBytesLog2(msize);
3468 SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003469}
3470
3471void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3472 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003473 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003474 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003475
Martyn Capewell1ac83572020-11-11 16:15:58 +00003476 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3477 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_d_64_unscaled")) ||
3478 (form_hash_ == Hash("stnt1d_z_p_ar_d_64_unscaled")) ||
3479 (form_hash_ == Hash("stnt1h_z_p_ar_d_64_unscaled")) ||
3480 (form_hash_ == Hash("stnt1w_z_p_ar_d_64_unscaled")));
3481
3482 addr.SetMsizeInBytesLog2(
3483 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3484 SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003485}
3486
3487void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3488 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003489 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003490 uint64_t xm = ReadXRegister(instr->GetRm());
3491
3492 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3493 int msize = -1;
3494 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003495
3496 switch (form_hash_) {
3497 case Hash("ldnt1b_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003498 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003499 break;
3500 case Hash("ldnt1h_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003501 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003502 break;
3503 case Hash("ldnt1sb_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003504 msize = 0;
3505 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003506 break;
3507 case Hash("ldnt1sh_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003508 msize = 1;
3509 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003510 break;
3511 case Hash("ldnt1w_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003512 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003513 break;
3514 default:
3515 VIXL_UNIMPLEMENTED();
3516 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003517 addr.SetMsizeInBytesLog2(msize);
3518 SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003519}
3520
3521void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3522 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003523 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003524 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003525
Martyn Capewell1ac83572020-11-11 16:15:58 +00003526 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3527 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_s_x32_unscaled")) ||
3528 (form_hash_ == Hash("stnt1h_z_p_ar_s_x32_unscaled")) ||
3529 (form_hash_ == Hash("stnt1w_z_p_ar_s_x32_unscaled")));
3530
3531 addr.SetMsizeInBytesLog2(
3532 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3533 SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003534}
3535
Jacob Bramley18c97bd2019-01-18 16:01:08 +00003536void Simulator::VisitReserved(const Instruction* instr) {
3537 // UDF is the only instruction in this group, and the Decoder is precise here.
3538 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3539
3540 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3541 reinterpret_cast<const void*>(instr),
3542 instr->GetInstructionBits());
3543 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3544}
3545
3546
Alexandre Ramesd3832962016-07-04 15:03:43 +01003547void Simulator::VisitUnimplemented(const Instruction* instr) {
3548 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3549 reinterpret_cast<const void*>(instr),
3550 instr->GetInstructionBits());
3551 VIXL_UNIMPLEMENTED();
3552}
3553
3554
3555void Simulator::VisitUnallocated(const Instruction* instr) {
3556 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3557 reinterpret_cast<const void*>(instr),
3558 instr->GetInstructionBits());
3559 VIXL_UNIMPLEMENTED();
3560}
3561
3562
3563void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3564 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3565 (instr->Mask(PCRelAddressingMask) == ADRP));
3566
3567 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3568}
3569
3570
3571void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3572 switch (instr->Mask(UnconditionalBranchMask)) {
3573 case BL:
3574 WriteLr(instr->GetNextInstruction());
3575 VIXL_FALLTHROUGH();
3576 case B:
3577 WritePc(instr->GetImmPCOffsetTarget());
3578 break;
3579 default:
3580 VIXL_UNREACHABLE();
3581 }
3582}
3583
3584
3585void Simulator::VisitConditionalBranch(const Instruction* instr) {
3586 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3587 if (ConditionPassed(instr->GetConditionBranch())) {
3588 WritePc(instr->GetImmPCOffsetTarget());
3589 }
3590}
3591
Martyn Capewellcb963f72018-10-22 15:25:28 +01003592BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3593 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3594 case BLR:
3595 case BLRAA:
3596 case BLRAB:
3597 case BLRAAZ:
3598 case BLRABZ:
3599 return BranchAndLink;
3600 case BR:
3601 case BRAA:
3602 case BRAB:
3603 case BRAAZ:
3604 case BRABZ:
3605 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3606 !PcIsInGuardedPage()) {
3607 return BranchFromUnguardedOrToIP;
3608 }
3609 return BranchFromGuardedNotToIP;
3610 }
3611 return DefaultBType;
3612}
Alexandre Ramesd3832962016-07-04 15:03:43 +01003613
3614void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003615 bool authenticate = false;
3616 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01003617 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01003618 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003619
3620 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3621 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01003622 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003623 VIXL_FALLTHROUGH();
3624 case BR:
3625 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01003626 break;
3627
3628 case BLRAAZ:
3629 case BLRABZ:
3630 link = true;
3631 VIXL_FALLTHROUGH();
3632 case BRAAZ:
3633 case BRABZ:
3634 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003635 break;
3636
3637 case BLRAA:
3638 case BLRAB:
3639 link = true;
3640 VIXL_FALLTHROUGH();
3641 case BRAA:
3642 case BRAB:
3643 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003644 context = ReadXRegister(instr->GetRd());
3645 break;
3646
3647 case RETAA:
3648 case RETAB:
3649 authenticate = true;
3650 addr = ReadXRegister(kLinkRegCode);
3651 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003652 break;
3653 default:
3654 VIXL_UNREACHABLE();
3655 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003656
3657 if (link) {
3658 WriteLr(instr->GetNextInstruction());
3659 }
3660
3661 if (authenticate) {
3662 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3663 addr = AuthPAC(addr, context, key, kInstructionPointer);
3664
3665 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3666 if (((addr >> error_lsb) & 0x3) != 0x0) {
3667 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3668 }
3669 }
3670
Martyn Capewellcb963f72018-10-22 15:25:28 +01003671 WritePc(Instruction::Cast(addr));
3672 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003673}
3674
3675
3676void Simulator::VisitTestBranch(const Instruction* instr) {
3677 unsigned bit_pos =
3678 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3679 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3680 bool take_branch = false;
3681 switch (instr->Mask(TestBranchMask)) {
3682 case TBZ:
3683 take_branch = bit_zero;
3684 break;
3685 case TBNZ:
3686 take_branch = !bit_zero;
3687 break;
3688 default:
3689 VIXL_UNIMPLEMENTED();
3690 }
3691 if (take_branch) {
3692 WritePc(instr->GetImmPCOffsetTarget());
3693 }
3694}
3695
3696
3697void Simulator::VisitCompareBranch(const Instruction* instr) {
3698 unsigned rt = instr->GetRt();
3699 bool take_branch = false;
3700 switch (instr->Mask(CompareBranchMask)) {
3701 case CBZ_w:
3702 take_branch = (ReadWRegister(rt) == 0);
3703 break;
3704 case CBZ_x:
3705 take_branch = (ReadXRegister(rt) == 0);
3706 break;
3707 case CBNZ_w:
3708 take_branch = (ReadWRegister(rt) != 0);
3709 break;
3710 case CBNZ_x:
3711 take_branch = (ReadXRegister(rt) != 0);
3712 break;
3713 default:
3714 VIXL_UNIMPLEMENTED();
3715 }
3716 if (take_branch) {
3717 WritePc(instr->GetImmPCOffsetTarget());
3718 }
3719}
3720
3721
3722void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3723 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3724 bool set_flags = instr->GetFlagsUpdate();
3725 int64_t new_val = 0;
3726 Instr operation = instr->Mask(AddSubOpMask);
3727
3728 switch (operation) {
3729 case ADD:
3730 case ADDS: {
3731 new_val = AddWithCarry(reg_size,
3732 set_flags,
3733 ReadRegister(reg_size,
3734 instr->GetRn(),
3735 instr->GetRnMode()),
3736 op2);
3737 break;
3738 }
3739 case SUB:
3740 case SUBS: {
3741 new_val = AddWithCarry(reg_size,
3742 set_flags,
3743 ReadRegister(reg_size,
3744 instr->GetRn(),
3745 instr->GetRnMode()),
3746 ~op2,
3747 1);
3748 break;
3749 }
3750 default:
3751 VIXL_UNREACHABLE();
3752 }
3753
3754 WriteRegister(reg_size,
3755 instr->GetRd(),
3756 new_val,
3757 LogRegWrites,
3758 instr->GetRdMode());
3759}
3760
3761
3762void Simulator::VisitAddSubShifted(const Instruction* instr) {
3763 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3764 int64_t op2 = ShiftOperand(reg_size,
3765 ReadRegister(reg_size, instr->GetRm()),
3766 static_cast<Shift>(instr->GetShiftDP()),
3767 instr->GetImmDPShift());
3768 AddSubHelper(instr, op2);
3769}
3770
3771
3772void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3773 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01003774 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003775 AddSubHelper(instr, op2);
3776}
3777
3778
3779void Simulator::VisitAddSubExtended(const Instruction* instr) {
3780 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3781 int64_t op2 = ExtendValue(reg_size,
3782 ReadRegister(reg_size, instr->GetRm()),
3783 static_cast<Extend>(instr->GetExtendMode()),
3784 instr->GetImmExtendShift());
3785 AddSubHelper(instr, op2);
3786}
3787
3788
3789void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3790 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3791 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3792 int64_t new_val;
3793
3794 if ((instr->Mask(AddSubOpMask) == SUB) ||
3795 (instr->Mask(AddSubOpMask) == SUBS)) {
3796 op2 = ~op2;
3797 }
3798
3799 new_val = AddWithCarry(reg_size,
3800 instr->GetFlagsUpdate(),
3801 ReadRegister(reg_size, instr->GetRn()),
3802 op2,
3803 ReadC());
3804
3805 WriteRegister(reg_size, instr->GetRd(), new_val);
3806}
3807
3808
Alexander Gilday2487f142018-11-05 13:07:27 +00003809void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3810 switch (instr->Mask(RotateRightIntoFlagsMask)) {
3811 case RMIF: {
3812 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3813 unsigned shift = instr->GetImmRMIFRotation();
3814 unsigned mask = instr->GetNzcv();
3815 uint64_t rotated = RotateRight(value, shift, kXRegSize);
3816
3817 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3818 break;
3819 }
3820 }
3821}
3822
3823
3824void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3825 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3826 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3827
3828 unsigned sign_bit = (value >> msb) & 1;
3829 unsigned overflow_bit = (value >> (msb + 1)) & 1;
3830 ReadNzcv().SetN(sign_bit);
3831 ReadNzcv().SetZ((value << (31 - msb)) == 0);
3832 ReadNzcv().SetV(sign_bit ^ overflow_bit);
3833}
3834
3835
Alexandre Ramesd3832962016-07-04 15:03:43 +01003836void Simulator::VisitLogicalShifted(const Instruction* instr) {
3837 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3838 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3839 unsigned shift_amount = instr->GetImmDPShift();
3840 int64_t op2 = ShiftOperand(reg_size,
3841 ReadRegister(reg_size, instr->GetRm()),
3842 shift_type,
3843 shift_amount);
3844 if (instr->Mask(NOT) == NOT) {
3845 op2 = ~op2;
3846 }
3847 LogicalHelper(instr, op2);
3848}
3849
3850
3851void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3852 LogicalHelper(instr, instr->GetImmLogical());
3853}
3854
3855
3856void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3857 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3858 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3859 int64_t result = 0;
3860 bool update_flags = false;
3861
3862 // Switch on the logical operation, stripping out the NOT bit, as it has a
3863 // different meaning for logical immediate instructions.
3864 switch (instr->Mask(LogicalOpMask & ~NOT)) {
3865 case ANDS:
3866 update_flags = true;
3867 VIXL_FALLTHROUGH();
3868 case AND:
3869 result = op1 & op2;
3870 break;
3871 case ORR:
3872 result = op1 | op2;
3873 break;
3874 case EOR:
3875 result = op1 ^ op2;
3876 break;
3877 default:
3878 VIXL_UNIMPLEMENTED();
3879 }
3880
3881 if (update_flags) {
3882 ReadNzcv().SetN(CalcNFlag(result, reg_size));
3883 ReadNzcv().SetZ(CalcZFlag(result));
3884 ReadNzcv().SetC(0);
3885 ReadNzcv().SetV(0);
3886 LogSystemRegister(NZCV);
3887 }
3888
3889 WriteRegister(reg_size,
3890 instr->GetRd(),
3891 result,
3892 LogRegWrites,
3893 instr->GetRdMode());
3894}
3895
3896
3897void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3898 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3899 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3900}
3901
3902
3903void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3904 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3905}
3906
3907
3908void Simulator::ConditionalCompareHelper(const Instruction* instr,
3909 int64_t op2) {
3910 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3911 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3912
3913 if (ConditionPassed(instr->GetCondition())) {
3914 // If the condition passes, set the status flags to the result of comparing
3915 // the operands.
3916 if (instr->Mask(ConditionalCompareMask) == CCMP) {
3917 AddWithCarry(reg_size, true, op1, ~op2, 1);
3918 } else {
3919 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3920 AddWithCarry(reg_size, true, op1, op2, 0);
3921 }
3922 } else {
3923 // If the condition fails, set the status flags to the nzcv immediate.
3924 ReadNzcv().SetFlags(instr->GetNzcv());
3925 LogSystemRegister(NZCV);
3926 }
3927}
3928
3929
3930void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3931 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3932 LoadStoreHelper(instr, offset, Offset);
3933}
3934
3935
3936void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3937 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3938}
3939
3940
3941void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3942 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3943}
3944
3945
3946void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3947 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3948}
3949
3950
Alexander Gilday311edf22018-10-29 13:41:41 +00003951template <typename T1, typename T2>
3952void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
3953 unsigned rt = instr->GetRt();
3954 unsigned rn = instr->GetRn();
3955
3956 unsigned element_size = sizeof(T2);
3957 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3958 int offset = instr->GetImmLS();
3959 address += offset;
3960
3961 // Verify that the address is available to the host.
3962 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3963
3964 // Check the alignment of `address`.
3965 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3966 VIXL_ALIGNMENT_EXCEPTION();
3967 }
3968
3969 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
3970
3971 // Approximate load-acquire by issuing a full barrier after the load.
3972 __sync_synchronize();
3973
Jacob Bramley423e5422019-11-13 19:15:55 +00003974 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003975}
3976
3977
3978template <typename T>
3979void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
3980 unsigned rt = instr->GetRt();
3981 unsigned rn = instr->GetRn();
3982
3983 unsigned element_size = sizeof(T);
3984 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3985 int offset = instr->GetImmLS();
3986 address += offset;
3987
3988 // Verify that the address is available to the host.
3989 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3990
3991 // Check the alignment of `address`.
3992 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3993 VIXL_ALIGNMENT_EXCEPTION();
3994 }
3995
3996 // Approximate store-release by issuing a full barrier after the load.
3997 __sync_synchronize();
3998
3999 Memory::Write<T>(address, ReadRegister<T>(rt));
4000
Jacob Bramley423e5422019-11-13 19:15:55 +00004001 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00004002}
4003
4004
4005void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
4006 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
4007 case LDAPURB:
4008 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
4009 break;
4010 case LDAPURH:
4011 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
4012 break;
4013 case LDAPUR_w:
4014 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
4015 break;
4016 case LDAPUR_x:
4017 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
4018 break;
4019 case LDAPURSB_w:
4020 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
4021 break;
4022 case LDAPURSB_x:
4023 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
4024 break;
4025 case LDAPURSH_w:
4026 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
4027 break;
4028 case LDAPURSH_x:
4029 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
4030 break;
4031 case LDAPURSW:
4032 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
4033 break;
4034 case STLURB:
4035 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
4036 break;
4037 case STLURH:
4038 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4039 break;
4040 case STLUR_w:
4041 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4042 break;
4043 case STLUR_x:
4044 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4045 break;
4046 }
4047}
4048
4049
Alexander Gilday75605592018-11-01 09:30:29 +00004050void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4051 unsigned dst = instr->GetRt();
4052 unsigned addr_reg = instr->GetRn();
4053
4054 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4055
4056 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4057 address = AuthPAC(address, 0, key, kDataPointer);
4058
4059 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4060 if (((address >> error_lsb) & 0x3) != 0x0) {
4061 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4062 }
4063
4064
4065 if ((addr_reg == 31) && ((address % 16) != 0)) {
4066 // When the base register is SP the stack pointer is required to be
4067 // quadword aligned prior to the address calculation and write-backs.
4068 // Misalignment will cause a stack alignment fault.
4069 VIXL_ALIGNMENT_EXCEPTION();
4070 }
4071
4072 int64_t offset = instr->GetImmLSPAC();
4073 address += offset;
4074
4075 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4076 // Pre-index mode.
4077 VIXL_ASSERT(offset != 0);
4078 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4079 }
4080
4081 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4082
4083 // Verify that the calculated address is available to the host.
4084 VIXL_ASSERT(address == addr_ptr);
4085
4086 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
4087 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00004088 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00004089}
4090
4091
Alexandre Ramesd3832962016-07-04 15:03:43 +01004092void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4093 Extend ext = static_cast<Extend>(instr->GetExtendMode());
4094 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4095 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4096
4097 int64_t offset =
4098 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4099 LoadStoreHelper(instr, offset, Offset);
4100}
4101
4102
4103void Simulator::LoadStoreHelper(const Instruction* instr,
4104 int64_t offset,
4105 AddrMode addrmode) {
4106 unsigned srcdst = instr->GetRt();
4107 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4108
Jacob Bramley423e5422019-11-13 19:15:55 +00004109 bool rt_is_vreg = false;
4110 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004111 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4112 switch (op) {
4113 case LDRB_w:
4114 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004115 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004116 break;
4117 case LDRH_w:
4118 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004119 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004120 break;
4121 case LDR_w:
4122 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004123 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 break;
4125 case LDR_x:
4126 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004127 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004128 break;
4129 case LDRSB_w:
4130 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004131 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004132 break;
4133 case LDRSH_w:
4134 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004135 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004136 break;
4137 case LDRSB_x:
4138 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004139 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004140 break;
4141 case LDRSH_x:
4142 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004143 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004144 break;
4145 case LDRSW_x:
4146 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004147 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004148 break;
4149 case LDR_b:
4150 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004151 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004152 break;
4153 case LDR_h:
4154 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004155 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004156 break;
4157 case LDR_s:
4158 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004159 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004160 break;
4161 case LDR_d:
4162 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004163 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004164 break;
4165 case LDR_q:
4166 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004167 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004168 break;
4169
4170 case STRB_w:
4171 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
4172 break;
4173 case STRH_w:
4174 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
4175 break;
4176 case STR_w:
4177 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
4178 break;
4179 case STR_x:
4180 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
4181 break;
4182 case STR_b:
4183 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004184 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004185 break;
4186 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01004187 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004188 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004189 break;
4190 case STR_s:
4191 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004192 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004193 break;
4194 case STR_d:
4195 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004196 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004197 break;
4198 case STR_q:
4199 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004200 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004201 break;
4202
4203 // Ignore prfm hint instructions.
4204 case PRFM:
4205 break;
4206
4207 default:
4208 VIXL_UNIMPLEMENTED();
4209 }
4210
Jacob Bramley423e5422019-11-13 19:15:55 +00004211 // Print a detailed trace (including the memory address).
4212 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004213 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00004214 unsigned result_size = extend ? extend_to_size : access_size;
4215 PrintRegisterFormat print_format =
4216 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4217 : GetPrintRegisterFormatForSize(result_size);
4218
Alexandre Ramesd3832962016-07-04 15:03:43 +01004219 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004220 if (rt_is_vreg) {
4221 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004222 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004223 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004224 }
4225 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004226 if (rt_is_vreg) {
4227 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004228 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004229 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004230 }
4231 } else {
4232 VIXL_ASSERT(op == PRFM);
4233 }
4234
4235 local_monitor_.MaybeClear();
4236}
4237
4238
4239void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4240 LoadStorePairHelper(instr, Offset);
4241}
4242
4243
4244void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4245 LoadStorePairHelper(instr, PreIndex);
4246}
4247
4248
4249void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4250 LoadStorePairHelper(instr, PostIndex);
4251}
4252
4253
4254void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4255 LoadStorePairHelper(instr, Offset);
4256}
4257
4258
4259void Simulator::LoadStorePairHelper(const Instruction* instr,
4260 AddrMode addrmode) {
4261 unsigned rt = instr->GetRt();
4262 unsigned rt2 = instr->GetRt2();
4263 int element_size = 1 << instr->GetSizeLSPair();
4264 int64_t offset = instr->GetImmLSPair() * element_size;
4265 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4266 uintptr_t address2 = address + element_size;
4267
4268 LoadStorePairOp op =
4269 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4270
4271 // 'rt' and 'rt2' can only be aliased for stores.
4272 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4273
Jacob Bramley423e5422019-11-13 19:15:55 +00004274 bool rt_is_vreg = false;
4275 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004276 switch (op) {
4277 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4278 // will print a more detailed log.
4279 case LDP_w: {
4280 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4281 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
4282 break;
4283 }
4284 case LDP_s: {
4285 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
4286 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004287 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004288 break;
4289 }
4290 case LDP_x: {
4291 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4292 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
4293 break;
4294 }
4295 case LDP_d: {
4296 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
4297 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004298 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004299 break;
4300 }
4301 case LDP_q: {
4302 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
4303 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004304 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004305 break;
4306 }
4307 case LDPSW_x: {
4308 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
4309 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004310 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004311 break;
4312 }
4313 case STP_w: {
4314 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4315 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
4316 break;
4317 }
4318 case STP_s: {
4319 Memory::Write<float>(address, ReadSRegister(rt));
4320 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004321 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004322 break;
4323 }
4324 case STP_x: {
4325 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4326 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
4327 break;
4328 }
4329 case STP_d: {
4330 Memory::Write<double>(address, ReadDRegister(rt));
4331 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004332 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004333 break;
4334 }
4335 case STP_q: {
4336 Memory::Write<qreg_t>(address, ReadQRegister(rt));
4337 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004338 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004339 break;
4340 }
4341 default:
4342 VIXL_UNREACHABLE();
4343 }
4344
Jacob Bramley423e5422019-11-13 19:15:55 +00004345 // Print a detailed trace (including the memory address).
4346 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4347 PrintRegisterFormat print_format =
4348 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4349 : GetPrintRegisterFormatForSize(result_size);
4350
Alexandre Ramesd3832962016-07-04 15:03:43 +01004351 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004352 if (rt_is_vreg) {
4353 LogVRead(rt, print_format, address);
4354 LogVRead(rt2, print_format, address2);
4355 } else if (sign_extend) {
4356 LogExtendingRead(rt, print_format, element_size, address);
4357 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004358 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004359 LogRead(rt, print_format, address);
4360 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004361 }
4362 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004363 if (rt_is_vreg) {
4364 LogVWrite(rt, print_format, address);
4365 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004366 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004367 LogWrite(rt, print_format, address);
4368 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004369 }
4370 }
4371
4372 local_monitor_.MaybeClear();
4373}
4374
4375
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004376template <typename T>
4377void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4378 unsigned rs = instr->GetRs();
4379 unsigned rt = instr->GetRt();
4380 unsigned rn = instr->GetRn();
4381
4382 unsigned element_size = sizeof(T);
4383 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4384
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004385 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4386
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004387 bool is_acquire = instr->ExtractBit(22) == 1;
4388 bool is_release = instr->ExtractBit(15) == 1;
4389
4390 T comparevalue = ReadRegister<T>(rs);
4391 T newvalue = ReadRegister<T>(rt);
4392
4393 // The architecture permits that the data read clears any exclusive monitors
4394 // associated with that location, even if the compare subsequently fails.
4395 local_monitor_.Clear();
4396
4397 T data = Memory::Read<T>(address);
4398 if (is_acquire) {
4399 // Approximate load-acquire by issuing a full barrier after the load.
4400 __sync_synchronize();
4401 }
4402
4403 if (data == comparevalue) {
4404 if (is_release) {
4405 // Approximate store-release by issuing a full barrier before the store.
4406 __sync_synchronize();
4407 }
4408 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00004409 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004410 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004411 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004412 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004413}
4414
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004415
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004416template <typename T>
4417void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4418 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4419 unsigned rs = instr->GetRs();
4420 unsigned rt = instr->GetRt();
4421 unsigned rn = instr->GetRn();
4422
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004423 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004424
4425 unsigned element_size = sizeof(T);
4426 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004427
4428 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4429
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004430 uint64_t address2 = address + element_size;
4431
4432 bool is_acquire = instr->ExtractBit(22) == 1;
4433 bool is_release = instr->ExtractBit(15) == 1;
4434
4435 T comparevalue_high = ReadRegister<T>(rs + 1);
4436 T comparevalue_low = ReadRegister<T>(rs);
4437 T newvalue_high = ReadRegister<T>(rt + 1);
4438 T newvalue_low = ReadRegister<T>(rt);
4439
4440 // The architecture permits that the data read clears any exclusive monitors
4441 // associated with that location, even if the compare subsequently fails.
4442 local_monitor_.Clear();
4443
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004444 T data_low = Memory::Read<T>(address);
4445 T data_high = Memory::Read<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004446
4447 if (is_acquire) {
4448 // Approximate load-acquire by issuing a full barrier after the load.
4449 __sync_synchronize();
4450 }
4451
4452 bool same =
4453 (data_high == comparevalue_high) && (data_low == comparevalue_low);
4454 if (same) {
4455 if (is_release) {
4456 // Approximate store-release by issuing a full barrier before the store.
4457 __sync_synchronize();
4458 }
4459
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004460 Memory::Write<T>(address, newvalue_low);
4461 Memory::Write<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004462 }
4463
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004464 WriteRegister<T>(rs + 1, data_high, NoRegLog);
4465 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004466
Jacob Bramley423e5422019-11-13 19:15:55 +00004467 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004468 LogRead(rs, format, address);
4469 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004470
4471 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004472 LogWrite(rt, format, address);
4473 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004474 }
4475}
4476
Jacob Bramley85a9c102019-12-09 17:48:29 +00004477bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4478 // To simulate fault-tolerant loads, we need to know what host addresses we
4479 // can access without generating a real fault. One way to do that is to
4480 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
4481 // and less intrusive than using (global) signal handlers.
4482 //
4483 // [1]: https://stackoverflow.com/questions/7134590
4484
4485 size_t written = 0;
4486 bool can_read = true;
4487 // `write` will normally return after one invocation, but it is allowed to
4488 // handle only part of the operation, so wrap it in a loop.
4489 while (can_read && (written < size)) {
4490 ssize_t result = write(dummy_pipe_fd_[1],
4491 reinterpret_cast<void*>(address + written),
4492 size - written);
4493 if (result > 0) {
4494 written += result;
4495 } else {
4496 switch (result) {
4497 case -EPERM:
4498 case -EFAULT:
4499 // The address range is not accessible.
4500 // `write` is supposed to return -EFAULT in this case, but in practice
4501 // it seems to return -EPERM, so we accept that too.
4502 can_read = false;
4503 break;
4504 case -EINTR:
4505 // The call was interrupted by a signal. Just try again.
4506 break;
4507 default:
4508 // Any other error is fatal.
4509 VIXL_ABORT();
4510 }
4511 }
4512 }
4513 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4514 // the dummy data is buffered. As before, we expect to drain the whole write
4515 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
4516 // function is primarily intended to implement SVE fault-tolerant loads, so
4517 // the maximum Z register size is a good default buffer size.
4518 char buffer[kZRegMaxSizeInBytes];
4519 while (written > 0) {
4520 ssize_t result = read(dummy_pipe_fd_[0],
4521 reinterpret_cast<void*>(buffer),
4522 sizeof(buffer));
4523 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4524 // we've read everything that was written, so treat 0 as an error.
4525 if (result > 0) {
4526 VIXL_ASSERT(static_cast<size_t>(result) <= written);
4527 written -= result;
4528 } else {
4529 // For -EINTR, just try again. We can't handle any other error.
4530 VIXL_CHECK(result == -EINTR);
4531 }
4532 }
4533
4534 return can_read;
4535}
Alexandre Ramesd3832962016-07-04 15:03:43 +01004536
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004537void Simulator::PrintExclusiveAccessWarning() {
4538 if (print_exclusive_access_warning_) {
4539 fprintf(stderr,
4540 "%sWARNING:%s VIXL simulator support for "
4541 "load-/store-/clear-exclusive "
4542 "instructions is limited. Refer to the README for details.%s\n",
4543 clr_warning,
4544 clr_warning_message,
4545 clr_normal);
4546 print_exclusive_access_warning_ = false;
4547 }
4548}
4549
Alexandre Ramesd3832962016-07-04 15:03:43 +01004550void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004551 LoadStoreExclusive op =
4552 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4553
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004554 switch (op) {
4555 case CAS_w:
4556 case CASA_w:
4557 case CASL_w:
4558 case CASAL_w:
4559 CompareAndSwapHelper<uint32_t>(instr);
4560 break;
4561 case CAS_x:
4562 case CASA_x:
4563 case CASL_x:
4564 case CASAL_x:
4565 CompareAndSwapHelper<uint64_t>(instr);
4566 break;
4567 case CASB:
4568 case CASAB:
4569 case CASLB:
4570 case CASALB:
4571 CompareAndSwapHelper<uint8_t>(instr);
4572 break;
4573 case CASH:
4574 case CASAH:
4575 case CASLH:
4576 case CASALH:
4577 CompareAndSwapHelper<uint16_t>(instr);
4578 break;
4579 case CASP_w:
4580 case CASPA_w:
4581 case CASPL_w:
4582 case CASPAL_w:
4583 CompareAndSwapPairHelper<uint32_t>(instr);
4584 break;
4585 case CASP_x:
4586 case CASPA_x:
4587 case CASPL_x:
4588 case CASPAL_x:
4589 CompareAndSwapPairHelper<uint64_t>(instr);
4590 break;
4591 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004592 PrintExclusiveAccessWarning();
4593
4594 unsigned rs = instr->GetRs();
4595 unsigned rt = instr->GetRt();
4596 unsigned rt2 = instr->GetRt2();
4597 unsigned rn = instr->GetRn();
4598
4599 bool is_exclusive = !instr->GetLdStXNotExclusive();
4600 bool is_acquire_release =
4601 !is_exclusive || instr->GetLdStXAcquireRelease();
4602 bool is_load = instr->GetLdStXLoad();
4603 bool is_pair = instr->GetLdStXPair();
4604
4605 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4606 unsigned access_size = is_pair ? element_size * 2 : element_size;
4607 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4608
4609 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4610
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004611 if (is_load) {
4612 if (is_exclusive) {
4613 local_monitor_.MarkExclusive(address, access_size);
4614 } else {
4615 // Any non-exclusive load can clear the local monitor as a side
4616 // effect. We don't need to do this, but it is useful to stress the
4617 // simulated code.
4618 local_monitor_.Clear();
4619 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004620
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004621 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4622 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00004623 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004624 switch (op) {
4625 case LDXRB_w:
4626 case LDAXRB_w:
4627 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004628 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004629 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004630 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004631 break;
4632 case LDXRH_w:
4633 case LDAXRH_w:
4634 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004635 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004636 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004637 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004638 break;
4639 case LDXR_w:
4640 case LDAXR_w:
4641 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004642 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004643 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004644 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004645 break;
4646 case LDXR_x:
4647 case LDAXR_x:
4648 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004649 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004650 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004651 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004652 break;
4653 case LDXP_w:
4654 case LDAXP_w:
4655 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4656 WriteWRegister(rt2,
4657 Memory::Read<uint32_t>(address + element_size),
4658 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004659 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004660 break;
4661 case LDXP_x:
4662 case LDAXP_x:
4663 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4664 WriteXRegister(rt2,
4665 Memory::Read<uint64_t>(address + element_size),
4666 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004667 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004668 break;
4669 default:
4670 VIXL_UNREACHABLE();
4671 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004672
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004673 if (is_acquire_release) {
4674 // Approximate load-acquire by issuing a full barrier after the load.
4675 __sync_synchronize();
4676 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004677
Jacob Bramley423e5422019-11-13 19:15:55 +00004678 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4679 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004680 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004681 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004682 }
4683 } else {
4684 if (is_acquire_release) {
4685 // Approximate store-release by issuing a full barrier before the
4686 // store.
4687 __sync_synchronize();
4688 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004689
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004690 bool do_store = true;
4691 if (is_exclusive) {
4692 do_store = local_monitor_.IsExclusive(address, access_size) &&
4693 global_monitor_.IsExclusive(address, access_size);
4694 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004695
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004696 // - All exclusive stores explicitly clear the local monitor.
4697 local_monitor_.Clear();
4698 } else {
4699 // - Any other store can clear the local monitor as a side effect.
4700 local_monitor_.MaybeClear();
4701 }
4702
4703 if (do_store) {
4704 switch (op) {
4705 case STXRB_w:
4706 case STLXRB_w:
4707 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004708 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004709 Memory::Write<uint8_t>(address, ReadWRegister(rt));
4710 break;
4711 case STXRH_w:
4712 case STLXRH_w:
4713 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004714 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004715 Memory::Write<uint16_t>(address, ReadWRegister(rt));
4716 break;
4717 case STXR_w:
4718 case STLXR_w:
4719 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004720 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004721 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4722 break;
4723 case STXR_x:
4724 case STLXR_x:
4725 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004726 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004727 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4728 break;
4729 case STXP_w:
4730 case STLXP_w:
4731 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4732 Memory::Write<uint32_t>(address + element_size,
4733 ReadWRegister(rt2));
4734 break;
4735 case STXP_x:
4736 case STLXP_x:
4737 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4738 Memory::Write<uint64_t>(address + element_size,
4739 ReadXRegister(rt2));
4740 break;
4741 default:
4742 VIXL_UNREACHABLE();
4743 }
4744
Jacob Bramley423e5422019-11-13 19:15:55 +00004745 PrintRegisterFormat format =
4746 GetPrintRegisterFormatForSize(element_size);
4747 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004748 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004749 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004750 }
4751 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004752 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004753 }
4754}
4755
Jacob Bramleyca789742018-09-13 14:25:46 +01004756template <typename T>
4757void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4758 unsigned rs = instr->GetRs();
4759 unsigned rt = instr->GetRt();
4760 unsigned rn = instr->GetRn();
4761
4762 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4763 bool is_release = instr->ExtractBit(22) == 1;
4764
4765 unsigned element_size = sizeof(T);
4766 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4767
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004768 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004769
4770 T value = ReadRegister<T>(rs);
4771
4772 T data = Memory::Read<T>(address);
4773
4774 if (is_acquire) {
4775 // Approximate load-acquire by issuing a full barrier after the load.
4776 __sync_synchronize();
4777 }
4778
4779 T result = 0;
4780 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4781 case LDADDOp:
4782 result = data + value;
4783 break;
4784 case LDCLROp:
4785 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4786 result = data & ~value;
4787 break;
4788 case LDEOROp:
4789 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4790 result = data ^ value;
4791 break;
4792 case LDSETOp:
4793 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4794 result = data | value;
4795 break;
4796
4797 // Signed/Unsigned difference is done via the templated type T.
4798 case LDSMAXOp:
4799 case LDUMAXOp:
4800 result = (data > value) ? data : value;
4801 break;
4802 case LDSMINOp:
4803 case LDUMINOp:
4804 result = (data > value) ? value : data;
4805 break;
4806 }
4807
4808 if (is_release) {
4809 // Approximate store-release by issuing a full barrier before the store.
4810 __sync_synchronize();
4811 }
4812
4813 Memory::Write<T>(address, result);
4814 WriteRegister<T>(rt, data, NoRegLog);
4815
Jacob Bramley423e5422019-11-13 19:15:55 +00004816 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4817 LogRead(rt, format, address);
4818 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004819}
4820
4821template <typename T>
4822void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4823 unsigned rs = instr->GetRs();
4824 unsigned rt = instr->GetRt();
4825 unsigned rn = instr->GetRn();
4826
4827 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4828 bool is_release = instr->ExtractBit(22) == 1;
4829
4830 unsigned element_size = sizeof(T);
4831 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4832
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004833 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004834
4835 T data = Memory::Read<T>(address);
4836 if (is_acquire) {
4837 // Approximate load-acquire by issuing a full barrier after the load.
4838 __sync_synchronize();
4839 }
4840
4841 if (is_release) {
4842 // Approximate store-release by issuing a full barrier before the store.
4843 __sync_synchronize();
4844 }
4845 Memory::Write<T>(address, ReadRegister<T>(rs));
4846
4847 WriteRegister<T>(rt, data);
4848
Jacob Bramley423e5422019-11-13 19:15:55 +00004849 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4850 LogRead(rt, format, address);
4851 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004852}
4853
4854template <typename T>
4855void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4856 unsigned rt = instr->GetRt();
4857 unsigned rn = instr->GetRn();
4858
4859 unsigned element_size = sizeof(T);
4860 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4861
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004862 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4863
Jacob Bramleyca789742018-09-13 14:25:46 +01004864 WriteRegister<T>(rt, Memory::Read<T>(address));
4865
4866 // Approximate load-acquire by issuing a full barrier after the load.
4867 __sync_synchronize();
4868
Jacob Bramley423e5422019-11-13 19:15:55 +00004869 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004870}
4871
4872#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4873 V(LDADD) \
4874 V(LDCLR) \
4875 V(LDEOR) \
4876 V(LDSET) \
4877 V(LDUMAX) \
4878 V(LDUMIN)
4879
4880#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4881 V(LDSMAX) \
4882 V(LDSMIN)
4883
4884void Simulator::VisitAtomicMemory(const Instruction* instr) {
4885 switch (instr->Mask(AtomicMemoryMask)) {
4886// clang-format off
4887#define SIM_FUNC_B(A) \
4888 case A##B: \
4889 case A##AB: \
4890 case A##LB: \
4891 case A##ALB:
4892#define SIM_FUNC_H(A) \
4893 case A##H: \
4894 case A##AH: \
4895 case A##LH: \
4896 case A##ALH:
4897#define SIM_FUNC_w(A) \
4898 case A##_w: \
4899 case A##A_w: \
4900 case A##L_w: \
4901 case A##AL_w:
4902#define SIM_FUNC_x(A) \
4903 case A##_x: \
4904 case A##A_x: \
4905 case A##L_x: \
4906 case A##AL_x:
4907
4908 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4909 AtomicMemorySimpleHelper<uint8_t>(instr);
4910 break;
4911 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4912 AtomicMemorySimpleHelper<int8_t>(instr);
4913 break;
4914 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4915 AtomicMemorySimpleHelper<uint16_t>(instr);
4916 break;
4917 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4918 AtomicMemorySimpleHelper<int16_t>(instr);
4919 break;
4920 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4921 AtomicMemorySimpleHelper<uint32_t>(instr);
4922 break;
4923 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4924 AtomicMemorySimpleHelper<int32_t>(instr);
4925 break;
4926 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4927 AtomicMemorySimpleHelper<uint64_t>(instr);
4928 break;
4929 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4930 AtomicMemorySimpleHelper<int64_t>(instr);
4931 break;
4932 // clang-format on
4933
4934 case SWPB:
4935 case SWPAB:
4936 case SWPLB:
4937 case SWPALB:
4938 AtomicMemorySwapHelper<uint8_t>(instr);
4939 break;
4940 case SWPH:
4941 case SWPAH:
4942 case SWPLH:
4943 case SWPALH:
4944 AtomicMemorySwapHelper<uint16_t>(instr);
4945 break;
4946 case SWP_w:
4947 case SWPA_w:
4948 case SWPL_w:
4949 case SWPAL_w:
4950 AtomicMemorySwapHelper<uint32_t>(instr);
4951 break;
4952 case SWP_x:
4953 case SWPA_x:
4954 case SWPL_x:
4955 case SWPAL_x:
4956 AtomicMemorySwapHelper<uint64_t>(instr);
4957 break;
4958 case LDAPRB:
4959 LoadAcquireRCpcHelper<uint8_t>(instr);
4960 break;
4961 case LDAPRH:
4962 LoadAcquireRCpcHelper<uint16_t>(instr);
4963 break;
4964 case LDAPR_w:
4965 LoadAcquireRCpcHelper<uint32_t>(instr);
4966 break;
4967 case LDAPR_x:
4968 LoadAcquireRCpcHelper<uint64_t>(instr);
4969 break;
4970 }
4971}
4972
Alexandre Ramesd3832962016-07-04 15:03:43 +01004973
4974void Simulator::VisitLoadLiteral(const Instruction* instr) {
4975 unsigned rt = instr->GetRt();
4976 uint64_t address = instr->GetLiteralAddress<uint64_t>();
4977
4978 // Verify that the calculated address is available to the host.
4979 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4980
4981 switch (instr->Mask(LoadLiteralMask)) {
4982 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
4983 // print a more detailed log.
4984 case LDR_w_lit:
4985 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004986 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004987 break;
4988 case LDR_x_lit:
4989 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004990 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004991 break;
4992 case LDR_s_lit:
4993 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004994 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004995 break;
4996 case LDR_d_lit:
4997 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004998 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004999 break;
5000 case LDR_q_lit:
5001 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005002 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005003 break;
5004 case LDRSW_x_lit:
5005 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005006 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005007 break;
5008
5009 // Ignore prfm hint instructions.
5010 case PRFM_lit:
5011 break;
5012
5013 default:
5014 VIXL_UNREACHABLE();
5015 }
5016
5017 local_monitor_.MaybeClear();
5018}
5019
5020
5021uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
5022 int64_t offset,
5023 AddrMode addrmode) {
5024 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
5025
5026 if ((addr_reg == 31) && ((address % 16) != 0)) {
5027 // When the base register is SP the stack pointer is required to be
5028 // quadword aligned prior to the address calculation and write-backs.
5029 // Misalignment will cause a stack alignment fault.
5030 VIXL_ALIGNMENT_EXCEPTION();
5031 }
5032
5033 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
5034 VIXL_ASSERT(offset != 0);
5035 // Only preindex should log the register update here. For Postindex, the
5036 // update will be printed automatically by LogWrittenRegisters _after_ the
5037 // memory access itself is logged.
5038 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5039 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5040 }
5041
5042 if ((addrmode == Offset) || (addrmode == PreIndex)) {
5043 address += offset;
5044 }
5045
5046 // Verify that the calculated address is available to the host.
5047 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5048
5049 return static_cast<uintptr_t>(address);
5050}
5051
5052
5053void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5054 MoveWideImmediateOp mov_op =
5055 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5056 int64_t new_xn_val = 0;
5057
5058 bool is_64_bits = instr->GetSixtyFourBits() == 1;
5059 // Shift is limited for W operations.
5060 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5061
5062 // Get the shifted immediate.
5063 int64_t shift = instr->GetShiftMoveWide() * 16;
5064 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5065 << shift;
5066
5067 // Compute the new value.
5068 switch (mov_op) {
5069 case MOVN_w:
5070 case MOVN_x: {
5071 new_xn_val = ~shifted_imm16;
5072 if (!is_64_bits) new_xn_val &= kWRegMask;
5073 break;
5074 }
5075 case MOVK_w:
5076 case MOVK_x: {
5077 unsigned reg_code = instr->GetRd();
5078 int64_t prev_xn_val =
5079 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5080 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5081 break;
5082 }
5083 case MOVZ_w:
5084 case MOVZ_x: {
5085 new_xn_val = shifted_imm16;
5086 break;
5087 }
5088 default:
5089 VIXL_UNREACHABLE();
5090 }
5091
5092 // Update the destination register.
5093 WriteXRegister(instr->GetRd(), new_xn_val);
5094}
5095
5096
5097void Simulator::VisitConditionalSelect(const Instruction* instr) {
5098 uint64_t new_val = ReadXRegister(instr->GetRn());
5099
5100 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5101 new_val = ReadXRegister(instr->GetRm());
5102 switch (instr->Mask(ConditionalSelectMask)) {
5103 case CSEL_w:
5104 case CSEL_x:
5105 break;
5106 case CSINC_w:
5107 case CSINC_x:
5108 new_val++;
5109 break;
5110 case CSINV_w:
5111 case CSINV_x:
5112 new_val = ~new_val;
5113 break;
5114 case CSNEG_w:
5115 case CSNEG_x:
5116 new_val = -new_val;
5117 break;
5118 default:
5119 VIXL_UNIMPLEMENTED();
5120 }
5121 }
5122 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5123 WriteRegister(reg_size, instr->GetRd(), new_val);
5124}
5125
5126
Jacob Bramleyca789742018-09-13 14:25:46 +01005127// clang-format off
5128#define PAUTH_MODES(V) \
5129 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
5130 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
5131 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
5132 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
5133 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
5134 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
5135 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
5136 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
5137// clang-format on
5138
Alexandre Ramesd3832962016-07-04 15:03:43 +01005139void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5140 unsigned dst = instr->GetRd();
5141 unsigned src = instr->GetRn();
5142
5143 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005144#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
5145 case PAC##SUFFIX: { \
5146 uint64_t ptr = ReadXRegister(dst); \
5147 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
5148 break; \
5149 } \
5150 case AUT##SUFFIX: { \
5151 uint64_t ptr = ReadXRegister(dst); \
5152 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
5153 break; \
5154 }
5155
5156 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
5157#undef DEFINE_PAUTH_FUNCS
5158
5159 case XPACI:
5160 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5161 break;
5162 case XPACD:
5163 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5164 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005165 case RBIT_w:
5166 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5167 break;
5168 case RBIT_x:
5169 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5170 break;
5171 case REV16_w:
5172 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5173 break;
5174 case REV16_x:
5175 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5176 break;
5177 case REV_w:
5178 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5179 break;
5180 case REV32_x:
5181 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5182 break;
5183 case REV_x:
5184 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5185 break;
5186 case CLZ_w:
5187 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5188 break;
5189 case CLZ_x:
5190 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5191 break;
5192 case CLS_w:
5193 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5194 break;
5195 case CLS_x:
5196 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5197 break;
5198 default:
5199 VIXL_UNIMPLEMENTED();
5200 }
5201}
5202
5203
5204uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5205 VIXL_ASSERT((n > 32) && (n <= 64));
5206 for (unsigned i = (n - 1); i >= 32; i--) {
5207 if (((data >> i) & 1) != 0) {
5208 uint64_t polysh32 = (uint64_t)poly << (i - 32);
5209 uint64_t mask = (UINT64_C(1) << i) - 1;
5210 data = ((data & mask) ^ polysh32);
5211 }
5212 }
5213 return data & 0xffffffff;
5214}
5215
5216
5217template <typename T>
5218uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5219 unsigned size = sizeof(val) * 8; // Number of bits in type T.
5220 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5221 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5222 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5223 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5224}
5225
5226
5227uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5228 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5229 // the CRC of each 32-bit word sequentially.
5230 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5231 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5232}
5233
5234
5235void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5236 Shift shift_op = NO_SHIFT;
5237 int64_t result = 0;
5238 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5239
5240 switch (instr->Mask(DataProcessing2SourceMask)) {
5241 case SDIV_w: {
5242 int32_t rn = ReadWRegister(instr->GetRn());
5243 int32_t rm = ReadWRegister(instr->GetRm());
5244 if ((rn == kWMinInt) && (rm == -1)) {
5245 result = kWMinInt;
5246 } else if (rm == 0) {
5247 // Division by zero can be trapped, but not on A-class processors.
5248 result = 0;
5249 } else {
5250 result = rn / rm;
5251 }
5252 break;
5253 }
5254 case SDIV_x: {
5255 int64_t rn = ReadXRegister(instr->GetRn());
5256 int64_t rm = ReadXRegister(instr->GetRm());
5257 if ((rn == kXMinInt) && (rm == -1)) {
5258 result = kXMinInt;
5259 } else if (rm == 0) {
5260 // Division by zero can be trapped, but not on A-class processors.
5261 result = 0;
5262 } else {
5263 result = rn / rm;
5264 }
5265 break;
5266 }
5267 case UDIV_w: {
5268 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5269 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5270 if (rm == 0) {
5271 // Division by zero can be trapped, but not on A-class processors.
5272 result = 0;
5273 } else {
5274 result = rn / rm;
5275 }
5276 break;
5277 }
5278 case UDIV_x: {
5279 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5280 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5281 if (rm == 0) {
5282 // Division by zero can be trapped, but not on A-class processors.
5283 result = 0;
5284 } else {
5285 result = rn / rm;
5286 }
5287 break;
5288 }
5289 case LSLV_w:
5290 case LSLV_x:
5291 shift_op = LSL;
5292 break;
5293 case LSRV_w:
5294 case LSRV_x:
5295 shift_op = LSR;
5296 break;
5297 case ASRV_w:
5298 case ASRV_x:
5299 shift_op = ASR;
5300 break;
5301 case RORV_w:
5302 case RORV_x:
5303 shift_op = ROR;
5304 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005305 case PACGA: {
5306 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5307 uint64_t src = static_cast<uint64_t>(
5308 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5309 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5310 result = code & 0xffffffff00000000;
5311 break;
5312 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005313 case CRC32B: {
5314 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5315 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5316 result = Crc32Checksum(acc, val, CRC32_POLY);
5317 break;
5318 }
5319 case CRC32H: {
5320 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5321 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5322 result = Crc32Checksum(acc, val, CRC32_POLY);
5323 break;
5324 }
5325 case CRC32W: {
5326 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5327 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5328 result = Crc32Checksum(acc, val, CRC32_POLY);
5329 break;
5330 }
5331 case CRC32X: {
5332 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5333 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5334 result = Crc32Checksum(acc, val, CRC32_POLY);
5335 reg_size = kWRegSize;
5336 break;
5337 }
5338 case CRC32CB: {
5339 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5340 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5341 result = Crc32Checksum(acc, val, CRC32C_POLY);
5342 break;
5343 }
5344 case CRC32CH: {
5345 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5346 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5347 result = Crc32Checksum(acc, val, CRC32C_POLY);
5348 break;
5349 }
5350 case CRC32CW: {
5351 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5352 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5353 result = Crc32Checksum(acc, val, CRC32C_POLY);
5354 break;
5355 }
5356 case CRC32CX: {
5357 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5358 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5359 result = Crc32Checksum(acc, val, CRC32C_POLY);
5360 reg_size = kWRegSize;
5361 break;
5362 }
5363 default:
5364 VIXL_UNIMPLEMENTED();
5365 }
5366
5367 if (shift_op != NO_SHIFT) {
5368 // Shift distance encoded in the least-significant five/six bits of the
5369 // register.
5370 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5371 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5372 result = ShiftOperand(reg_size,
5373 ReadRegister(reg_size, instr->GetRn()),
5374 shift_op,
5375 shift);
5376 }
5377 WriteRegister(reg_size, instr->GetRd(), result);
5378}
5379
5380
Alexandre Ramesd3832962016-07-04 15:03:43 +01005381void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5382 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5383
5384 uint64_t result = 0;
5385 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5386 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5387 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5388 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5389 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005390 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5391 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005392 switch (instr->Mask(DataProcessing3SourceMask)) {
5393 case MADD_w:
5394 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005395 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005396 break;
5397 case MSUB_w:
5398 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005399 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005400 break;
5401 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005402 result = ReadXRegister(instr->GetRa()) +
5403 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005404 break;
5405 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005406 result = ReadXRegister(instr->GetRa()) -
5407 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005408 break;
5409 case UMADDL_x:
5410 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5411 break;
5412 case UMSUBL_x:
5413 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5414 break;
5415 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005416 result =
5417 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5418 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005419 break;
5420 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005421 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5422 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005423 break;
5424 default:
5425 VIXL_UNIMPLEMENTED();
5426 }
5427 WriteRegister(reg_size, instr->GetRd(), result);
5428}
5429
5430
5431void Simulator::VisitBitfield(const Instruction* instr) {
5432 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5433 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005434 int R = instr->GetImmR();
5435 int S = instr->GetImmS();
5436 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005437 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005438 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005439 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005440 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005441 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005442 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005443 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005444 diff += reg_size;
5445 }
5446
5447 // inzero indicates if the extracted bitfield is inserted into the
5448 // destination register value or in zero.
5449 // If extend is true, extend the sign of the extracted bitfield.
5450 bool inzero = false;
5451 bool extend = false;
5452 switch (instr->Mask(BitfieldMask)) {
5453 case BFM_x:
5454 case BFM_w:
5455 break;
5456 case SBFM_x:
5457 case SBFM_w:
5458 inzero = true;
5459 extend = true;
5460 break;
5461 case UBFM_x:
5462 case UBFM_w:
5463 inzero = true;
5464 break;
5465 default:
5466 VIXL_UNIMPLEMENTED();
5467 }
5468
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005469 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5470 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005471 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005472 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005473 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005474 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5475 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005476
5477 // Merge sign extension, dest/zero and bitfield.
5478 result = signbits | (result & mask) | (dst & ~mask);
5479
5480 WriteRegister(reg_size, instr->GetRd(), result);
5481}
5482
5483
5484void Simulator::VisitExtract(const Instruction* instr) {
5485 unsigned lsb = instr->GetImmS();
5486 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5487 uint64_t low_res =
5488 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00005489 uint64_t high_res = (lsb == 0)
5490 ? 0
5491 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5492 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005493 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5494}
5495
5496
5497void Simulator::VisitFPImmediate(const Instruction* instr) {
5498 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005499 unsigned dest = instr->GetRd();
5500 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005501 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01005502 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01005503 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005504 case FMOV_s_imm:
5505 WriteSRegister(dest, instr->GetImmFP32());
5506 break;
5507 case FMOV_d_imm:
5508 WriteDRegister(dest, instr->GetImmFP64());
5509 break;
5510 default:
5511 VIXL_UNREACHABLE();
5512 }
5513}
5514
5515
5516void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5517 AssertSupportedFPCR();
5518
5519 unsigned dst = instr->GetRd();
5520 unsigned src = instr->GetRn();
5521
5522 FPRounding round = ReadRMode();
5523
5524 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005525 case FCVTAS_wh:
5526 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5527 break;
5528 case FCVTAS_xh:
5529 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5530 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005531 case FCVTAS_ws:
5532 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5533 break;
5534 case FCVTAS_xs:
5535 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5536 break;
5537 case FCVTAS_wd:
5538 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5539 break;
5540 case FCVTAS_xd:
5541 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5542 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005543 case FCVTAU_wh:
5544 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5545 break;
5546 case FCVTAU_xh:
5547 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5548 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005549 case FCVTAU_ws:
5550 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5551 break;
5552 case FCVTAU_xs:
5553 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5554 break;
5555 case FCVTAU_wd:
5556 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5557 break;
5558 case FCVTAU_xd:
5559 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5560 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005561 case FCVTMS_wh:
5562 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5563 break;
5564 case FCVTMS_xh:
5565 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5566 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005567 case FCVTMS_ws:
5568 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5569 break;
5570 case FCVTMS_xs:
5571 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5572 break;
5573 case FCVTMS_wd:
5574 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5575 break;
5576 case FCVTMS_xd:
5577 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5578 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005579 case FCVTMU_wh:
5580 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5581 break;
5582 case FCVTMU_xh:
5583 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5584 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005585 case FCVTMU_ws:
5586 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5587 break;
5588 case FCVTMU_xs:
5589 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5590 break;
5591 case FCVTMU_wd:
5592 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5593 break;
5594 case FCVTMU_xd:
5595 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5596 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005597 case FCVTPS_wh:
5598 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5599 break;
5600 case FCVTPS_xh:
5601 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5602 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005603 case FCVTPS_ws:
5604 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5605 break;
5606 case FCVTPS_xs:
5607 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5608 break;
5609 case FCVTPS_wd:
5610 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5611 break;
5612 case FCVTPS_xd:
5613 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5614 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005615 case FCVTPU_wh:
5616 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5617 break;
5618 case FCVTPU_xh:
5619 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5620 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005621 case FCVTPU_ws:
5622 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5623 break;
5624 case FCVTPU_xs:
5625 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5626 break;
5627 case FCVTPU_wd:
5628 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5629 break;
5630 case FCVTPU_xd:
5631 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5632 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005633 case FCVTNS_wh:
5634 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5635 break;
5636 case FCVTNS_xh:
5637 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5638 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005639 case FCVTNS_ws:
5640 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5641 break;
5642 case FCVTNS_xs:
5643 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5644 break;
5645 case FCVTNS_wd:
5646 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5647 break;
5648 case FCVTNS_xd:
5649 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5650 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005651 case FCVTNU_wh:
5652 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5653 break;
5654 case FCVTNU_xh:
5655 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5656 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005657 case FCVTNU_ws:
5658 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5659 break;
5660 case FCVTNU_xs:
5661 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5662 break;
5663 case FCVTNU_wd:
5664 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5665 break;
5666 case FCVTNU_xd:
5667 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5668 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005669 case FCVTZS_wh:
5670 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5671 break;
5672 case FCVTZS_xh:
5673 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5674 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005675 case FCVTZS_ws:
5676 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5677 break;
5678 case FCVTZS_xs:
5679 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5680 break;
5681 case FCVTZS_wd:
5682 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5683 break;
5684 case FCVTZS_xd:
5685 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5686 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005687 case FCVTZU_wh:
5688 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5689 break;
5690 case FCVTZU_xh:
5691 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5692 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005693 case FCVTZU_ws:
5694 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5695 break;
5696 case FCVTZU_xs:
5697 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5698 break;
5699 case FCVTZU_wd:
5700 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5701 break;
5702 case FCVTZU_xd:
5703 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5704 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005705 case FJCVTZS:
5706 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5707 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005708 case FMOV_hw:
5709 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5710 break;
5711 case FMOV_wh:
5712 WriteWRegister(dst, ReadHRegisterBits(src));
5713 break;
5714 case FMOV_xh:
5715 WriteXRegister(dst, ReadHRegisterBits(src));
5716 break;
5717 case FMOV_hx:
5718 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5719 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005720 case FMOV_ws:
5721 WriteWRegister(dst, ReadSRegisterBits(src));
5722 break;
5723 case FMOV_xd:
5724 WriteXRegister(dst, ReadDRegisterBits(src));
5725 break;
5726 case FMOV_sw:
5727 WriteSRegisterBits(dst, ReadWRegister(src));
5728 break;
5729 case FMOV_dx:
5730 WriteDRegisterBits(dst, ReadXRegister(src));
5731 break;
5732 case FMOV_d1_x:
5733 LogicVRegister(ReadVRegister(dst))
5734 .SetUint(kFormatD, 1, ReadXRegister(src));
5735 break;
5736 case FMOV_x_d1:
5737 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5738 break;
5739
5740 // A 32-bit input can be handled in the same way as a 64-bit input, since
5741 // the sign- or zero-extension will not affect the conversion.
5742 case SCVTF_dx:
5743 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5744 break;
5745 case SCVTF_dw:
5746 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5747 break;
5748 case UCVTF_dx:
5749 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5750 break;
5751 case UCVTF_dw: {
5752 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005753 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005754 break;
5755 }
5756 case SCVTF_sx:
5757 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5758 break;
5759 case SCVTF_sw:
5760 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5761 break;
5762 case UCVTF_sx:
5763 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5764 break;
5765 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01005766 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5767 break;
5768 }
5769 case SCVTF_hx:
5770 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5771 break;
5772 case SCVTF_hw:
5773 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5774 break;
5775 case UCVTF_hx:
5776 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5777 break;
5778 case UCVTF_hw: {
5779 WriteHRegister(dst,
5780 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005781 break;
5782 }
5783
5784 default:
5785 VIXL_UNREACHABLE();
5786 }
5787}
5788
5789
5790void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5791 AssertSupportedFPCR();
5792
5793 unsigned dst = instr->GetRd();
5794 unsigned src = instr->GetRn();
5795 int fbits = 64 - instr->GetFPScale();
5796
5797 FPRounding round = ReadRMode();
5798
5799 switch (instr->Mask(FPFixedPointConvertMask)) {
5800 // A 32-bit input can be handled in the same way as a 64-bit input, since
5801 // the sign- or zero-extension will not affect the conversion.
5802 case SCVTF_dx_fixed:
5803 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5804 break;
5805 case SCVTF_dw_fixed:
5806 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5807 break;
5808 case UCVTF_dx_fixed:
5809 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5810 break;
5811 case UCVTF_dw_fixed: {
5812 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005813 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005814 break;
5815 }
5816 case SCVTF_sx_fixed:
5817 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5818 break;
5819 case SCVTF_sw_fixed:
5820 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5821 break;
5822 case UCVTF_sx_fixed:
5823 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5824 break;
5825 case UCVTF_sw_fixed: {
5826 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005827 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5828 break;
5829 }
5830 case SCVTF_hx_fixed:
5831 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5832 break;
5833 case SCVTF_hw_fixed:
5834 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5835 break;
5836 case UCVTF_hx_fixed:
5837 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5838 break;
5839 case UCVTF_hw_fixed: {
5840 WriteHRegister(dst,
5841 UFixedToFloat16(ReadRegister<uint32_t>(src),
5842 fbits,
5843 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005844 break;
5845 }
5846 case FCVTZS_xd_fixed:
5847 WriteXRegister(dst,
5848 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5849 FPZero));
5850 break;
5851 case FCVTZS_wd_fixed:
5852 WriteWRegister(dst,
5853 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5854 FPZero));
5855 break;
5856 case FCVTZU_xd_fixed:
5857 WriteXRegister(dst,
5858 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5859 FPZero));
5860 break;
5861 case FCVTZU_wd_fixed:
5862 WriteWRegister(dst,
5863 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5864 FPZero));
5865 break;
5866 case FCVTZS_xs_fixed:
5867 WriteXRegister(dst,
5868 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5869 FPZero));
5870 break;
5871 case FCVTZS_ws_fixed:
5872 WriteWRegister(dst,
5873 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5874 FPZero));
5875 break;
5876 case FCVTZU_xs_fixed:
5877 WriteXRegister(dst,
5878 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5879 FPZero));
5880 break;
5881 case FCVTZU_ws_fixed:
5882 WriteWRegister(dst,
5883 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5884 FPZero));
5885 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005886 case FCVTZS_xh_fixed: {
5887 double output =
5888 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5889 WriteXRegister(dst, FPToInt64(output, FPZero));
5890 break;
5891 }
5892 case FCVTZS_wh_fixed: {
5893 double output =
5894 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5895 WriteWRegister(dst, FPToInt32(output, FPZero));
5896 break;
5897 }
5898 case FCVTZU_xh_fixed: {
5899 double output =
5900 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5901 WriteXRegister(dst, FPToUInt64(output, FPZero));
5902 break;
5903 }
5904 case FCVTZU_wh_fixed: {
5905 double output =
5906 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5907 WriteWRegister(dst, FPToUInt32(output, FPZero));
5908 break;
5909 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005910 default:
5911 VIXL_UNREACHABLE();
5912 }
5913}
5914
5915
5916void Simulator::VisitFPCompare(const Instruction* instr) {
5917 AssertSupportedFPCR();
5918
5919 FPTrapFlags trap = DisableTrap;
5920 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005921 case FCMPE_h:
5922 trap = EnableTrap;
5923 VIXL_FALLTHROUGH();
5924 case FCMP_h:
5925 FPCompare(ReadHRegister(instr->GetRn()),
5926 ReadHRegister(instr->GetRm()),
5927 trap);
5928 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005929 case FCMPE_s:
5930 trap = EnableTrap;
5931 VIXL_FALLTHROUGH();
5932 case FCMP_s:
5933 FPCompare(ReadSRegister(instr->GetRn()),
5934 ReadSRegister(instr->GetRm()),
5935 trap);
5936 break;
5937 case FCMPE_d:
5938 trap = EnableTrap;
5939 VIXL_FALLTHROUGH();
5940 case FCMP_d:
5941 FPCompare(ReadDRegister(instr->GetRn()),
5942 ReadDRegister(instr->GetRm()),
5943 trap);
5944 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005945 case FCMPE_h_zero:
5946 trap = EnableTrap;
5947 VIXL_FALLTHROUGH();
5948 case FCMP_h_zero:
5949 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5950 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005951 case FCMPE_s_zero:
5952 trap = EnableTrap;
5953 VIXL_FALLTHROUGH();
5954 case FCMP_s_zero:
5955 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
5956 break;
5957 case FCMPE_d_zero:
5958 trap = EnableTrap;
5959 VIXL_FALLTHROUGH();
5960 case FCMP_d_zero:
5961 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
5962 break;
5963 default:
5964 VIXL_UNIMPLEMENTED();
5965 }
5966}
5967
5968
5969void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
5970 AssertSupportedFPCR();
5971
5972 FPTrapFlags trap = DisableTrap;
5973 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005974 case FCCMPE_h:
5975 trap = EnableTrap;
5976 VIXL_FALLTHROUGH();
5977 case FCCMP_h:
5978 if (ConditionPassed(instr->GetCondition())) {
5979 FPCompare(ReadHRegister(instr->GetRn()),
5980 ReadHRegister(instr->GetRm()),
5981 trap);
5982 } else {
5983 ReadNzcv().SetFlags(instr->GetNzcv());
5984 LogSystemRegister(NZCV);
5985 }
5986 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005987 case FCCMPE_s:
5988 trap = EnableTrap;
5989 VIXL_FALLTHROUGH();
5990 case FCCMP_s:
5991 if (ConditionPassed(instr->GetCondition())) {
5992 FPCompare(ReadSRegister(instr->GetRn()),
5993 ReadSRegister(instr->GetRm()),
5994 trap);
5995 } else {
5996 ReadNzcv().SetFlags(instr->GetNzcv());
5997 LogSystemRegister(NZCV);
5998 }
5999 break;
6000 case FCCMPE_d:
6001 trap = EnableTrap;
6002 VIXL_FALLTHROUGH();
6003 case FCCMP_d:
6004 if (ConditionPassed(instr->GetCondition())) {
6005 FPCompare(ReadDRegister(instr->GetRn()),
6006 ReadDRegister(instr->GetRm()),
6007 trap);
6008 } else {
6009 ReadNzcv().SetFlags(instr->GetNzcv());
6010 LogSystemRegister(NZCV);
6011 }
6012 break;
6013 default:
6014 VIXL_UNIMPLEMENTED();
6015 }
6016}
6017
6018
6019void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
6020 AssertSupportedFPCR();
6021
6022 Instr selected;
6023 if (ConditionPassed(instr->GetCondition())) {
6024 selected = instr->GetRn();
6025 } else {
6026 selected = instr->GetRm();
6027 }
6028
6029 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006030 case FCSEL_h:
6031 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
6032 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006033 case FCSEL_s:
6034 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
6035 break;
6036 case FCSEL_d:
6037 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6038 break;
6039 default:
6040 VIXL_UNIMPLEMENTED();
6041 }
6042}
6043
6044
6045void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6046 AssertSupportedFPCR();
6047
6048 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006049 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006050 switch (instr->Mask(FPTypeMask)) {
6051 default:
6052 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6053 case FP64:
6054 vform = kFormatD;
6055 break;
6056 case FP32:
6057 vform = kFormatS;
6058 break;
6059 case FP16:
6060 vform = kFormatH;
6061 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006062 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006063
Alexandre Ramesd3832962016-07-04 15:03:43 +01006064 SimVRegister& rd = ReadVRegister(instr->GetRd());
6065 SimVRegister& rn = ReadVRegister(instr->GetRn());
6066 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006067 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006068
6069 unsigned fd = instr->GetRd();
6070 unsigned fn = instr->GetRn();
6071
6072 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01006073 case FMOV_h:
6074 WriteHRegister(fd, ReadHRegister(fn));
6075 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006076 case FMOV_s:
6077 WriteSRegister(fd, ReadSRegister(fn));
6078 return;
6079 case FMOV_d:
6080 WriteDRegister(fd, ReadDRegister(fn));
6081 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006082 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006083 case FABS_s:
6084 case FABS_d:
6085 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6086 // Explicitly log the register update whilst we have type information.
6087 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6088 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006089 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006090 case FNEG_s:
6091 case FNEG_d:
6092 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6093 // Explicitly log the register update whilst we have type information.
6094 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6095 return;
6096 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01006097 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006098 return;
6099 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01006100 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006101 return;
6102 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01006103 WriteHRegister(fd,
6104 Float16ToRawbits(
6105 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006106 return;
6107 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01006108 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006109 return;
6110 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01006111 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006112 return;
6113 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01006114 WriteHRegister(fd,
6115 Float16ToRawbits(
6116 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006117 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006118 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006119 case FSQRT_s:
6120 case FSQRT_d:
6121 fsqrt(vform, rd, rn);
6122 // Explicitly log the register update whilst we have type information.
6123 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6124 return;
TatWai Chong04471812019-03-19 14:29:00 -07006125 case FRINT32X_s:
6126 case FRINT32X_d:
6127 inexact_exception = true;
6128 frint_mode = kFrintToInt32;
6129 break; // Use FPCR rounding mode.
6130 case FRINT64X_s:
6131 case FRINT64X_d:
6132 inexact_exception = true;
6133 frint_mode = kFrintToInt64;
6134 break; // Use FPCR rounding mode.
6135 case FRINT32Z_s:
6136 case FRINT32Z_d:
6137 inexact_exception = true;
6138 frint_mode = kFrintToInt32;
6139 fpcr_rounding = FPZero;
6140 break;
6141 case FRINT64Z_s:
6142 case FRINT64Z_d:
6143 inexact_exception = true;
6144 frint_mode = kFrintToInt64;
6145 fpcr_rounding = FPZero;
6146 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006147 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006148 case FRINTI_s:
6149 case FRINTI_d:
6150 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01006151 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006152 case FRINTX_s:
6153 case FRINTX_d:
6154 inexact_exception = true;
6155 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006156 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006157 case FRINTA_s:
6158 case FRINTA_d:
6159 fpcr_rounding = FPTieAway;
6160 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006161 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006162 case FRINTM_s:
6163 case FRINTM_d:
6164 fpcr_rounding = FPNegativeInfinity;
6165 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006166 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006167 case FRINTN_s:
6168 case FRINTN_d:
6169 fpcr_rounding = FPTieEven;
6170 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006171 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006172 case FRINTP_s:
6173 case FRINTP_d:
6174 fpcr_rounding = FPPositiveInfinity;
6175 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006176 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006177 case FRINTZ_s:
6178 case FRINTZ_d:
6179 fpcr_rounding = FPZero;
6180 break;
6181 default:
6182 VIXL_UNIMPLEMENTED();
6183 }
6184
6185 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006186 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006187 // Explicitly log the register update whilst we have type information.
6188 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6189}
6190
6191
6192void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6193 AssertSupportedFPCR();
6194
Carey Williamsd8bb3572018-04-10 11:58:07 +01006195 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006196 switch (instr->Mask(FPTypeMask)) {
6197 default:
6198 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6199 case FP64:
6200 vform = kFormatD;
6201 break;
6202 case FP32:
6203 vform = kFormatS;
6204 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006205 case FP16:
6206 vform = kFormatH;
6207 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006208 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006209 SimVRegister& rd = ReadVRegister(instr->GetRd());
6210 SimVRegister& rn = ReadVRegister(instr->GetRn());
6211 SimVRegister& rm = ReadVRegister(instr->GetRm());
6212
6213 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006214 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006215 case FADD_s:
6216 case FADD_d:
6217 fadd(vform, rd, rn, rm);
6218 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006219 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006220 case FSUB_s:
6221 case FSUB_d:
6222 fsub(vform, rd, rn, rm);
6223 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006224 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006225 case FMUL_s:
6226 case FMUL_d:
6227 fmul(vform, rd, rn, rm);
6228 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006229 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006230 case FNMUL_s:
6231 case FNMUL_d:
6232 fnmul(vform, rd, rn, rm);
6233 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006234 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006235 case FDIV_s:
6236 case FDIV_d:
6237 fdiv(vform, rd, rn, rm);
6238 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006239 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006240 case FMAX_s:
6241 case FMAX_d:
6242 fmax(vform, rd, rn, rm);
6243 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006244 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006245 case FMIN_s:
6246 case FMIN_d:
6247 fmin(vform, rd, rn, rm);
6248 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006249 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006250 case FMAXNM_s:
6251 case FMAXNM_d:
6252 fmaxnm(vform, rd, rn, rm);
6253 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006254 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006255 case FMINNM_s:
6256 case FMINNM_d:
6257 fminnm(vform, rd, rn, rm);
6258 break;
6259 default:
6260 VIXL_UNREACHABLE();
6261 }
6262 // Explicitly log the register update whilst we have type information.
6263 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6264}
6265
6266
6267void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6268 AssertSupportedFPCR();
6269
6270 unsigned fd = instr->GetRd();
6271 unsigned fn = instr->GetRn();
6272 unsigned fm = instr->GetRm();
6273 unsigned fa = instr->GetRa();
6274
6275 switch (instr->Mask(FPDataProcessing3SourceMask)) {
6276 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01006277 case FMADD_h:
6278 WriteHRegister(fd,
6279 FPMulAdd(ReadHRegister(fa),
6280 ReadHRegister(fn),
6281 ReadHRegister(fm)));
6282 break;
6283 case FMSUB_h:
6284 WriteHRegister(fd,
6285 FPMulAdd(ReadHRegister(fa),
6286 -ReadHRegister(fn),
6287 ReadHRegister(fm)));
6288 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006289 case FMADD_s:
6290 WriteSRegister(fd,
6291 FPMulAdd(ReadSRegister(fa),
6292 ReadSRegister(fn),
6293 ReadSRegister(fm)));
6294 break;
6295 case FMSUB_s:
6296 WriteSRegister(fd,
6297 FPMulAdd(ReadSRegister(fa),
6298 -ReadSRegister(fn),
6299 ReadSRegister(fm)));
6300 break;
6301 case FMADD_d:
6302 WriteDRegister(fd,
6303 FPMulAdd(ReadDRegister(fa),
6304 ReadDRegister(fn),
6305 ReadDRegister(fm)));
6306 break;
6307 case FMSUB_d:
6308 WriteDRegister(fd,
6309 FPMulAdd(ReadDRegister(fa),
6310 -ReadDRegister(fn),
6311 ReadDRegister(fm)));
6312 break;
6313 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01006314 case FNMADD_h:
6315 WriteHRegister(fd,
6316 FPMulAdd(-ReadHRegister(fa),
6317 -ReadHRegister(fn),
6318 ReadHRegister(fm)));
6319 break;
6320 case FNMSUB_h:
6321 WriteHRegister(fd,
6322 FPMulAdd(-ReadHRegister(fa),
6323 ReadHRegister(fn),
6324 ReadHRegister(fm)));
6325 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006326 case FNMADD_s:
6327 WriteSRegister(fd,
6328 FPMulAdd(-ReadSRegister(fa),
6329 -ReadSRegister(fn),
6330 ReadSRegister(fm)));
6331 break;
6332 case FNMSUB_s:
6333 WriteSRegister(fd,
6334 FPMulAdd(-ReadSRegister(fa),
6335 ReadSRegister(fn),
6336 ReadSRegister(fm)));
6337 break;
6338 case FNMADD_d:
6339 WriteDRegister(fd,
6340 FPMulAdd(-ReadDRegister(fa),
6341 -ReadDRegister(fn),
6342 ReadDRegister(fm)));
6343 break;
6344 case FNMSUB_d:
6345 WriteDRegister(fd,
6346 FPMulAdd(-ReadDRegister(fa),
6347 ReadDRegister(fn),
6348 ReadDRegister(fm)));
6349 break;
6350 default:
6351 VIXL_UNIMPLEMENTED();
6352 }
6353}
6354
6355
6356bool Simulator::FPProcessNaNs(const Instruction* instr) {
6357 unsigned fd = instr->GetRd();
6358 unsigned fn = instr->GetRn();
6359 unsigned fm = instr->GetRm();
6360 bool done = false;
6361
6362 if (instr->Mask(FP64) == FP64) {
6363 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006364 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006365 WriteDRegister(fd, result);
6366 done = true;
6367 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006368 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006369 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006370 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006371 WriteSRegister(fd, result);
6372 done = true;
6373 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006374 } else {
6375 VIXL_ASSERT(instr->Mask(FP16) == FP16);
6376 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006377 }
6378
6379 return done;
6380}
6381
6382
6383void Simulator::SysOp_W(int op, int64_t val) {
6384 switch (op) {
6385 case IVAU:
6386 case CVAC:
6387 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01006388 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08006389 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006390 case CIVAC: {
6391 // Perform a dummy memory access to ensure that we have read access
6392 // to the specified address.
6393 volatile uint8_t y = Memory::Read<uint8_t>(val);
6394 USE(y);
6395 // TODO: Implement "case ZVA:".
6396 break;
6397 }
6398 default:
6399 VIXL_UNIMPLEMENTED();
6400 }
6401}
6402
6403
Jacob Bramleyca789742018-09-13 14:25:46 +01006404// clang-format off
6405#define PAUTH_SYSTEM_MODES(V) \
6406 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
6407 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
6408 V(AZ, 30, 0x00000000, kPACKeyIA) \
6409 V(BZ, 30, 0x00000000, kPACKeyIB) \
6410 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6411 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6412// clang-format on
6413
6414
Alexandre Ramesd3832962016-07-04 15:03:43 +01006415void Simulator::VisitSystem(const Instruction* instr) {
6416 // Some system instructions hijack their Op and Cp fields to represent a
6417 // range of immediates instead of indicating a different instruction. This
6418 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01006419 if (instr->GetInstructionBits() == XPACLRI) {
6420 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00006421 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6422 switch (instr->Mask(SystemPStateMask)) {
6423 case CFINV:
6424 ReadNzcv().SetC(!ReadC());
6425 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00006426 case AXFLAG:
6427 ReadNzcv().SetN(0);
6428 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6429 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6430 ReadNzcv().SetV(0);
6431 break;
6432 case XAFLAG: {
6433 // Can't set the flags in place due to the logical dependencies.
6434 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6435 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6436 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6437 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6438 ReadNzcv().SetN(n);
6439 ReadNzcv().SetZ(z);
6440 ReadNzcv().SetC(c);
6441 ReadNzcv().SetV(v);
6442 break;
6443 }
Alexander Gilday2487f142018-11-05 13:07:27 +00006444 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006445 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006446 // Check BType allows PACI[AB]SP instructions.
6447 if (PcIsInGuardedPage()) {
6448 Instr i = instr->Mask(SystemPAuthMask);
6449 if ((i == PACIASP) || (i == PACIBSP)) {
6450 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006451 case BranchFromGuardedNotToIP:
6452 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6453 // assume here to be zero. This allows execution of PACI[AB]SP when
6454 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00006455 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006456 case BranchFromUnguardedOrToIP:
6457 case BranchAndLink:
6458 break;
6459 }
6460 }
6461 }
6462
Jacob Bramleyca789742018-09-13 14:25:46 +01006463 switch (instr->Mask(SystemPAuthMask)) {
6464#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
6465 case PACI##SUFFIX: \
6466 WriteXRegister(DST, \
6467 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6468 break; \
6469 case AUTI##SUFFIX: \
6470 WriteXRegister(DST, \
6471 AuthPAC(ReadXRegister(DST), \
6472 MOD, \
6473 KEY, \
6474 kInstructionPointer)); \
6475 break;
6476
6477 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6478#undef DEFINE_PAUTH_FUNCS
6479 }
6480 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6481 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006482 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6483 switch (instr->Mask(SystemExclusiveMonitorMask)) {
6484 case CLREX: {
6485 PrintExclusiveAccessWarning();
6486 ClearLocalMonitor();
6487 break;
6488 }
6489 }
6490 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6491 switch (instr->Mask(SystemSysRegMask)) {
6492 case MRS: {
6493 switch (instr->GetImmSystemRegister()) {
6494 case NZCV:
6495 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6496 break;
6497 case FPCR:
6498 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6499 break;
TatWai Chong04edf682018-12-27 16:01:02 -08006500 case RNDR:
6501 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00006502 uint64_t high = jrand48(rand_state_);
6503 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08006504 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6505 WriteXRegister(instr->GetRt(), rand_num);
6506 // Simulate successful random number generation.
6507 // TODO: Return failure occasionally as a random number cannot be
6508 // returned in a period of time.
6509 ReadNzcv().SetRawValue(NoFlag);
6510 LogSystemRegister(NZCV);
6511 break;
6512 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006513 default:
6514 VIXL_UNIMPLEMENTED();
6515 }
6516 break;
6517 }
6518 case MSR: {
6519 switch (instr->GetImmSystemRegister()) {
6520 case NZCV:
6521 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6522 LogSystemRegister(NZCV);
6523 break;
6524 case FPCR:
6525 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6526 LogSystemRegister(FPCR);
6527 break;
6528 default:
6529 VIXL_UNIMPLEMENTED();
6530 }
6531 break;
6532 }
6533 }
6534 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6535 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6536 switch (instr->GetImmHint()) {
6537 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01006538 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00006539 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006540 case BTI_jc:
6541 break;
6542 case BTI:
6543 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6544 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6545 }
6546 break;
6547 case BTI_c:
6548 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6549 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6550 }
6551 break;
6552 case BTI_j:
6553 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6554 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6555 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006556 break;
6557 default:
6558 VIXL_UNIMPLEMENTED();
6559 }
6560 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6561 __sync_synchronize();
6562 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6563 switch (instr->Mask(SystemSysMask)) {
6564 case SYS:
6565 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6566 break;
6567 default:
6568 VIXL_UNIMPLEMENTED();
6569 }
6570 } else {
6571 VIXL_UNIMPLEMENTED();
6572 }
6573}
6574
6575
6576void Simulator::VisitException(const Instruction* instr) {
6577 switch (instr->Mask(ExceptionMask)) {
6578 case HLT:
6579 switch (instr->GetImmException()) {
6580 case kUnreachableOpcode:
6581 DoUnreachable(instr);
6582 return;
6583 case kTraceOpcode:
6584 DoTrace(instr);
6585 return;
6586 case kLogOpcode:
6587 DoLog(instr);
6588 return;
6589 case kPrintfOpcode:
6590 DoPrintf(instr);
6591 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01006592 case kRuntimeCallOpcode:
6593 DoRuntimeCall(instr);
6594 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01006595 case kSetCPUFeaturesOpcode:
6596 case kEnableCPUFeaturesOpcode:
6597 case kDisableCPUFeaturesOpcode:
6598 DoConfigureCPUFeatures(instr);
6599 return;
6600 case kSaveCPUFeaturesOpcode:
6601 DoSaveCPUFeatures(instr);
6602 return;
6603 case kRestoreCPUFeaturesOpcode:
6604 DoRestoreCPUFeatures(instr);
6605 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006606 default:
6607 HostBreakpoint();
6608 return;
6609 }
6610 case BRK:
6611 HostBreakpoint();
6612 return;
6613 default:
6614 VIXL_UNIMPLEMENTED();
6615 }
6616}
6617
6618
6619void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6620 VisitUnimplemented(instr);
6621}
6622
6623
6624void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6625 VisitUnimplemented(instr);
6626}
6627
6628
6629void Simulator::VisitCryptoAES(const Instruction* instr) {
6630 VisitUnimplemented(instr);
6631}
6632
6633
6634void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6635 NEONFormatDecoder nfd(instr);
6636 VectorFormat vf = nfd.GetVectorFormat();
6637
6638 static const NEONFormatMap map_lp =
6639 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6640 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6641
6642 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6643 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6644
6645 static const NEONFormatMap map_fcvtn = {{22, 30},
6646 {NF_4H, NF_8H, NF_2S, NF_4S}};
6647 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6648
6649 SimVRegister& rd = ReadVRegister(instr->GetRd());
6650 SimVRegister& rn = ReadVRegister(instr->GetRn());
6651
6652 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6653 // These instructions all use a two bit size field, except NOT and RBIT,
6654 // which use the field to encode the operation.
6655 switch (instr->Mask(NEON2RegMiscMask)) {
6656 case NEON_REV64:
6657 rev64(vf, rd, rn);
6658 break;
6659 case NEON_REV32:
6660 rev32(vf, rd, rn);
6661 break;
6662 case NEON_REV16:
6663 rev16(vf, rd, rn);
6664 break;
6665 case NEON_SUQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006666 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006667 break;
6668 case NEON_USQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006669 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006670 break;
6671 case NEON_CLS:
6672 cls(vf, rd, rn);
6673 break;
6674 case NEON_CLZ:
6675 clz(vf, rd, rn);
6676 break;
6677 case NEON_CNT:
6678 cnt(vf, rd, rn);
6679 break;
6680 case NEON_SQABS:
6681 abs(vf, rd, rn).SignedSaturate(vf);
6682 break;
6683 case NEON_SQNEG:
6684 neg(vf, rd, rn).SignedSaturate(vf);
6685 break;
6686 case NEON_CMGT_zero:
6687 cmp(vf, rd, rn, 0, gt);
6688 break;
6689 case NEON_CMGE_zero:
6690 cmp(vf, rd, rn, 0, ge);
6691 break;
6692 case NEON_CMEQ_zero:
6693 cmp(vf, rd, rn, 0, eq);
6694 break;
6695 case NEON_CMLE_zero:
6696 cmp(vf, rd, rn, 0, le);
6697 break;
6698 case NEON_CMLT_zero:
6699 cmp(vf, rd, rn, 0, lt);
6700 break;
6701 case NEON_ABS:
6702 abs(vf, rd, rn);
6703 break;
6704 case NEON_NEG:
6705 neg(vf, rd, rn);
6706 break;
6707 case NEON_SADDLP:
6708 saddlp(vf_lp, rd, rn);
6709 break;
6710 case NEON_UADDLP:
6711 uaddlp(vf_lp, rd, rn);
6712 break;
6713 case NEON_SADALP:
6714 sadalp(vf_lp, rd, rn);
6715 break;
6716 case NEON_UADALP:
6717 uadalp(vf_lp, rd, rn);
6718 break;
6719 case NEON_RBIT_NOT:
6720 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6721 switch (instr->GetFPType()) {
6722 case 0:
6723 not_(vf, rd, rn);
6724 break;
6725 case 1:
6726 rbit(vf, rd, rn);
6727 break;
6728 default:
6729 VIXL_UNIMPLEMENTED();
6730 }
6731 break;
6732 }
6733 } else {
6734 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6735 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6736 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006737 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006738
6739 // These instructions all use a one bit size field, except XTN, SQXTUN,
6740 // SHLL, SQXTN and UQXTN, which use a two bit size field.
6741 switch (instr->Mask(NEON2RegMiscFPMask)) {
6742 case NEON_FABS:
6743 fabs_(fpf, rd, rn);
6744 return;
6745 case NEON_FNEG:
6746 fneg(fpf, rd, rn);
6747 return;
6748 case NEON_FSQRT:
6749 fsqrt(fpf, rd, rn);
6750 return;
6751 case NEON_FCVTL:
6752 if (instr->Mask(NEON_Q)) {
6753 fcvtl2(vf_fcvtl, rd, rn);
6754 } else {
6755 fcvtl(vf_fcvtl, rd, rn);
6756 }
6757 return;
6758 case NEON_FCVTN:
6759 if (instr->Mask(NEON_Q)) {
6760 fcvtn2(vf_fcvtn, rd, rn);
6761 } else {
6762 fcvtn(vf_fcvtn, rd, rn);
6763 }
6764 return;
6765 case NEON_FCVTXN:
6766 if (instr->Mask(NEON_Q)) {
6767 fcvtxn2(vf_fcvtn, rd, rn);
6768 } else {
6769 fcvtxn(vf_fcvtn, rd, rn);
6770 }
6771 return;
6772
6773 // The following instructions break from the switch statement, rather
6774 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07006775 case NEON_FRINT32X:
6776 inexact_exception = true;
6777 frint_mode = kFrintToInt32;
6778 break; // Use FPCR rounding mode.
6779 case NEON_FRINT32Z:
6780 inexact_exception = true;
6781 frint_mode = kFrintToInt32;
6782 fpcr_rounding = FPZero;
6783 break;
6784 case NEON_FRINT64X:
6785 inexact_exception = true;
6786 frint_mode = kFrintToInt64;
6787 break; // Use FPCR rounding mode.
6788 case NEON_FRINT64Z:
6789 inexact_exception = true;
6790 frint_mode = kFrintToInt64;
6791 fpcr_rounding = FPZero;
6792 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006793 case NEON_FRINTI:
6794 break; // Use FPCR rounding mode.
6795 case NEON_FRINTX:
6796 inexact_exception = true;
6797 break;
6798 case NEON_FRINTA:
6799 fpcr_rounding = FPTieAway;
6800 break;
6801 case NEON_FRINTM:
6802 fpcr_rounding = FPNegativeInfinity;
6803 break;
6804 case NEON_FRINTN:
6805 fpcr_rounding = FPTieEven;
6806 break;
6807 case NEON_FRINTP:
6808 fpcr_rounding = FPPositiveInfinity;
6809 break;
6810 case NEON_FRINTZ:
6811 fpcr_rounding = FPZero;
6812 break;
6813
6814 case NEON_FCVTNS:
6815 fcvts(fpf, rd, rn, FPTieEven);
6816 return;
6817 case NEON_FCVTNU:
6818 fcvtu(fpf, rd, rn, FPTieEven);
6819 return;
6820 case NEON_FCVTPS:
6821 fcvts(fpf, rd, rn, FPPositiveInfinity);
6822 return;
6823 case NEON_FCVTPU:
6824 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6825 return;
6826 case NEON_FCVTMS:
6827 fcvts(fpf, rd, rn, FPNegativeInfinity);
6828 return;
6829 case NEON_FCVTMU:
6830 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6831 return;
6832 case NEON_FCVTZS:
6833 fcvts(fpf, rd, rn, FPZero);
6834 return;
6835 case NEON_FCVTZU:
6836 fcvtu(fpf, rd, rn, FPZero);
6837 return;
6838 case NEON_FCVTAS:
6839 fcvts(fpf, rd, rn, FPTieAway);
6840 return;
6841 case NEON_FCVTAU:
6842 fcvtu(fpf, rd, rn, FPTieAway);
6843 return;
6844 case NEON_SCVTF:
6845 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6846 return;
6847 case NEON_UCVTF:
6848 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6849 return;
6850 case NEON_URSQRTE:
6851 ursqrte(fpf, rd, rn);
6852 return;
6853 case NEON_URECPE:
6854 urecpe(fpf, rd, rn);
6855 return;
6856 case NEON_FRSQRTE:
6857 frsqrte(fpf, rd, rn);
6858 return;
6859 case NEON_FRECPE:
6860 frecpe(fpf, rd, rn, fpcr_rounding);
6861 return;
6862 case NEON_FCMGT_zero:
6863 fcmp_zero(fpf, rd, rn, gt);
6864 return;
6865 case NEON_FCMGE_zero:
6866 fcmp_zero(fpf, rd, rn, ge);
6867 return;
6868 case NEON_FCMEQ_zero:
6869 fcmp_zero(fpf, rd, rn, eq);
6870 return;
6871 case NEON_FCMLE_zero:
6872 fcmp_zero(fpf, rd, rn, le);
6873 return;
6874 case NEON_FCMLT_zero:
6875 fcmp_zero(fpf, rd, rn, lt);
6876 return;
6877 default:
6878 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6879 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6880 switch (instr->Mask(NEON2RegMiscMask)) {
6881 case NEON_XTN:
6882 xtn(vf, rd, rn);
6883 return;
6884 case NEON_SQXTN:
6885 sqxtn(vf, rd, rn);
6886 return;
6887 case NEON_UQXTN:
6888 uqxtn(vf, rd, rn);
6889 return;
6890 case NEON_SQXTUN:
6891 sqxtun(vf, rd, rn);
6892 return;
6893 case NEON_SHLL:
6894 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6895 if (instr->Mask(NEON_Q)) {
6896 shll2(vf, rd, rn);
6897 } else {
6898 shll(vf, rd, rn);
6899 }
6900 return;
6901 default:
6902 VIXL_UNIMPLEMENTED();
6903 }
6904 } else {
6905 VIXL_UNIMPLEMENTED();
6906 }
6907 }
6908
6909 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006910 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006911 }
6912}
6913
6914
Jacob Bramleyca789742018-09-13 14:25:46 +01006915void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6916 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6917 NEONFormatDecoder nfd(instr);
6918 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6919
6920 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6921
6922 SimVRegister& rd = ReadVRegister(instr->GetRd());
6923 SimVRegister& rn = ReadVRegister(instr->GetRn());
6924
6925 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6926 case NEON_SCVTF_H:
6927 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6928 return;
6929 case NEON_UCVTF_H:
6930 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6931 return;
6932 case NEON_FCVTNS_H:
6933 fcvts(fpf, rd, rn, FPTieEven);
6934 return;
6935 case NEON_FCVTNU_H:
6936 fcvtu(fpf, rd, rn, FPTieEven);
6937 return;
6938 case NEON_FCVTPS_H:
6939 fcvts(fpf, rd, rn, FPPositiveInfinity);
6940 return;
6941 case NEON_FCVTPU_H:
6942 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6943 return;
6944 case NEON_FCVTMS_H:
6945 fcvts(fpf, rd, rn, FPNegativeInfinity);
6946 return;
6947 case NEON_FCVTMU_H:
6948 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6949 return;
6950 case NEON_FCVTZS_H:
6951 fcvts(fpf, rd, rn, FPZero);
6952 return;
6953 case NEON_FCVTZU_H:
6954 fcvtu(fpf, rd, rn, FPZero);
6955 return;
6956 case NEON_FCVTAS_H:
6957 fcvts(fpf, rd, rn, FPTieAway);
6958 return;
6959 case NEON_FCVTAU_H:
6960 fcvtu(fpf, rd, rn, FPTieAway);
6961 return;
6962 case NEON_FRINTI_H:
6963 frint(fpf, rd, rn, fpcr_rounding, false);
6964 return;
6965 case NEON_FRINTX_H:
6966 frint(fpf, rd, rn, fpcr_rounding, true);
6967 return;
6968 case NEON_FRINTA_H:
6969 frint(fpf, rd, rn, FPTieAway, false);
6970 return;
6971 case NEON_FRINTM_H:
6972 frint(fpf, rd, rn, FPNegativeInfinity, false);
6973 return;
6974 case NEON_FRINTN_H:
6975 frint(fpf, rd, rn, FPTieEven, false);
6976 return;
6977 case NEON_FRINTP_H:
6978 frint(fpf, rd, rn, FPPositiveInfinity, false);
6979 return;
6980 case NEON_FRINTZ_H:
6981 frint(fpf, rd, rn, FPZero, false);
6982 return;
6983 case NEON_FABS_H:
6984 fabs_(fpf, rd, rn);
6985 return;
6986 case NEON_FNEG_H:
6987 fneg(fpf, rd, rn);
6988 return;
6989 case NEON_FSQRT_H:
6990 fsqrt(fpf, rd, rn);
6991 return;
6992 case NEON_FRSQRTE_H:
6993 frsqrte(fpf, rd, rn);
6994 return;
6995 case NEON_FRECPE_H:
6996 frecpe(fpf, rd, rn, fpcr_rounding);
6997 return;
6998 case NEON_FCMGT_H_zero:
6999 fcmp_zero(fpf, rd, rn, gt);
7000 return;
7001 case NEON_FCMGE_H_zero:
7002 fcmp_zero(fpf, rd, rn, ge);
7003 return;
7004 case NEON_FCMEQ_H_zero:
7005 fcmp_zero(fpf, rd, rn, eq);
7006 return;
7007 case NEON_FCMLE_H_zero:
7008 fcmp_zero(fpf, rd, rn, le);
7009 return;
7010 case NEON_FCMLT_H_zero:
7011 fcmp_zero(fpf, rd, rn, lt);
7012 return;
7013 default:
7014 VIXL_UNIMPLEMENTED();
7015 return;
7016 }
7017}
7018
7019
Alexandre Ramesd3832962016-07-04 15:03:43 +01007020void Simulator::VisitNEON3Same(const Instruction* instr) {
7021 NEONFormatDecoder nfd(instr);
7022 SimVRegister& rd = ReadVRegister(instr->GetRd());
7023 SimVRegister& rn = ReadVRegister(instr->GetRn());
7024 SimVRegister& rm = ReadVRegister(instr->GetRm());
7025
7026 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
7027 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7028 switch (instr->Mask(NEON3SameLogicalMask)) {
7029 case NEON_AND:
7030 and_(vf, rd, rn, rm);
7031 break;
7032 case NEON_ORR:
7033 orr(vf, rd, rn, rm);
7034 break;
7035 case NEON_ORN:
7036 orn(vf, rd, rn, rm);
7037 break;
7038 case NEON_EOR:
7039 eor(vf, rd, rn, rm);
7040 break;
7041 case NEON_BIC:
7042 bic(vf, rd, rn, rm);
7043 break;
7044 case NEON_BIF:
7045 bif(vf, rd, rn, rm);
7046 break;
7047 case NEON_BIT:
7048 bit(vf, rd, rn, rm);
7049 break;
7050 case NEON_BSL:
Martyn Capewellb1b95782020-10-23 15:59:49 +01007051 bsl(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007052 break;
7053 default:
7054 VIXL_UNIMPLEMENTED();
7055 }
7056 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7057 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7058 switch (instr->Mask(NEON3SameFPMask)) {
7059 case NEON_FADD:
7060 fadd(vf, rd, rn, rm);
7061 break;
7062 case NEON_FSUB:
7063 fsub(vf, rd, rn, rm);
7064 break;
7065 case NEON_FMUL:
7066 fmul(vf, rd, rn, rm);
7067 break;
7068 case NEON_FDIV:
7069 fdiv(vf, rd, rn, rm);
7070 break;
7071 case NEON_FMAX:
7072 fmax(vf, rd, rn, rm);
7073 break;
7074 case NEON_FMIN:
7075 fmin(vf, rd, rn, rm);
7076 break;
7077 case NEON_FMAXNM:
7078 fmaxnm(vf, rd, rn, rm);
7079 break;
7080 case NEON_FMINNM:
7081 fminnm(vf, rd, rn, rm);
7082 break;
7083 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007084 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007085 break;
7086 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007087 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007088 break;
7089 case NEON_FMULX:
7090 fmulx(vf, rd, rn, rm);
7091 break;
7092 case NEON_FACGE:
7093 fabscmp(vf, rd, rn, rm, ge);
7094 break;
7095 case NEON_FACGT:
7096 fabscmp(vf, rd, rn, rm, gt);
7097 break;
7098 case NEON_FCMEQ:
7099 fcmp(vf, rd, rn, rm, eq);
7100 break;
7101 case NEON_FCMGE:
7102 fcmp(vf, rd, rn, rm, ge);
7103 break;
7104 case NEON_FCMGT:
7105 fcmp(vf, rd, rn, rm, gt);
7106 break;
7107 case NEON_FRECPS:
7108 frecps(vf, rd, rn, rm);
7109 break;
7110 case NEON_FRSQRTS:
7111 frsqrts(vf, rd, rn, rm);
7112 break;
7113 case NEON_FABD:
7114 fabd(vf, rd, rn, rm);
7115 break;
7116 case NEON_FADDP:
7117 faddp(vf, rd, rn, rm);
7118 break;
7119 case NEON_FMAXP:
7120 fmaxp(vf, rd, rn, rm);
7121 break;
7122 case NEON_FMAXNMP:
7123 fmaxnmp(vf, rd, rn, rm);
7124 break;
7125 case NEON_FMINP:
7126 fminp(vf, rd, rn, rm);
7127 break;
7128 case NEON_FMINNMP:
7129 fminnmp(vf, rd, rn, rm);
7130 break;
7131 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007132 // FMLAL{2} and FMLSL{2} have special-case encodings.
7133 switch (instr->Mask(NEON3SameFHMMask)) {
7134 case NEON_FMLAL:
7135 fmlal(vf, rd, rn, rm);
7136 break;
7137 case NEON_FMLAL2:
7138 fmlal2(vf, rd, rn, rm);
7139 break;
7140 case NEON_FMLSL:
7141 fmlsl(vf, rd, rn, rm);
7142 break;
7143 case NEON_FMLSL2:
7144 fmlsl2(vf, rd, rn, rm);
7145 break;
7146 default:
7147 VIXL_UNIMPLEMENTED();
7148 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007149 }
7150 } else {
7151 VectorFormat vf = nfd.GetVectorFormat();
7152 switch (instr->Mask(NEON3SameMask)) {
7153 case NEON_ADD:
7154 add(vf, rd, rn, rm);
7155 break;
7156 case NEON_ADDP:
7157 addp(vf, rd, rn, rm);
7158 break;
7159 case NEON_CMEQ:
7160 cmp(vf, rd, rn, rm, eq);
7161 break;
7162 case NEON_CMGE:
7163 cmp(vf, rd, rn, rm, ge);
7164 break;
7165 case NEON_CMGT:
7166 cmp(vf, rd, rn, rm, gt);
7167 break;
7168 case NEON_CMHI:
7169 cmp(vf, rd, rn, rm, hi);
7170 break;
7171 case NEON_CMHS:
7172 cmp(vf, rd, rn, rm, hs);
7173 break;
7174 case NEON_CMTST:
7175 cmptst(vf, rd, rn, rm);
7176 break;
7177 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01007178 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007179 break;
7180 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01007181 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007182 break;
7183 case NEON_MUL:
7184 mul(vf, rd, rn, rm);
7185 break;
7186 case NEON_PMUL:
7187 pmul(vf, rd, rn, rm);
7188 break;
7189 case NEON_SMAX:
7190 smax(vf, rd, rn, rm);
7191 break;
7192 case NEON_SMAXP:
7193 smaxp(vf, rd, rn, rm);
7194 break;
7195 case NEON_SMIN:
7196 smin(vf, rd, rn, rm);
7197 break;
7198 case NEON_SMINP:
7199 sminp(vf, rd, rn, rm);
7200 break;
7201 case NEON_SUB:
7202 sub(vf, rd, rn, rm);
7203 break;
7204 case NEON_UMAX:
7205 umax(vf, rd, rn, rm);
7206 break;
7207 case NEON_UMAXP:
7208 umaxp(vf, rd, rn, rm);
7209 break;
7210 case NEON_UMIN:
7211 umin(vf, rd, rn, rm);
7212 break;
7213 case NEON_UMINP:
7214 uminp(vf, rd, rn, rm);
7215 break;
7216 case NEON_SSHL:
7217 sshl(vf, rd, rn, rm);
7218 break;
7219 case NEON_USHL:
7220 ushl(vf, rd, rn, rm);
7221 break;
7222 case NEON_SABD:
7223 absdiff(vf, rd, rn, rm, true);
7224 break;
7225 case NEON_UABD:
7226 absdiff(vf, rd, rn, rm, false);
7227 break;
7228 case NEON_SABA:
7229 saba(vf, rd, rn, rm);
7230 break;
7231 case NEON_UABA:
7232 uaba(vf, rd, rn, rm);
7233 break;
7234 case NEON_UQADD:
7235 add(vf, rd, rn, rm).UnsignedSaturate(vf);
7236 break;
7237 case NEON_SQADD:
7238 add(vf, rd, rn, rm).SignedSaturate(vf);
7239 break;
7240 case NEON_UQSUB:
7241 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7242 break;
7243 case NEON_SQSUB:
7244 sub(vf, rd, rn, rm).SignedSaturate(vf);
7245 break;
7246 case NEON_SQDMULH:
7247 sqdmulh(vf, rd, rn, rm);
7248 break;
7249 case NEON_SQRDMULH:
7250 sqrdmulh(vf, rd, rn, rm);
7251 break;
7252 case NEON_UQSHL:
7253 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7254 break;
7255 case NEON_SQSHL:
7256 sshl(vf, rd, rn, rm).SignedSaturate(vf);
7257 break;
7258 case NEON_URSHL:
7259 ushl(vf, rd, rn, rm).Round(vf);
7260 break;
7261 case NEON_SRSHL:
7262 sshl(vf, rd, rn, rm).Round(vf);
7263 break;
7264 case NEON_UQRSHL:
7265 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7266 break;
7267 case NEON_SQRSHL:
7268 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7269 break;
7270 case NEON_UHADD:
7271 add(vf, rd, rn, rm).Uhalve(vf);
7272 break;
7273 case NEON_URHADD:
7274 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7275 break;
7276 case NEON_SHADD:
7277 add(vf, rd, rn, rm).Halve(vf);
7278 break;
7279 case NEON_SRHADD:
7280 add(vf, rd, rn, rm).Halve(vf).Round(vf);
7281 break;
7282 case NEON_UHSUB:
7283 sub(vf, rd, rn, rm).Uhalve(vf);
7284 break;
7285 case NEON_SHSUB:
7286 sub(vf, rd, rn, rm).Halve(vf);
7287 break;
7288 default:
7289 VIXL_UNIMPLEMENTED();
7290 }
7291 }
7292}
7293
7294
Jacob Bramleyca789742018-09-13 14:25:46 +01007295void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7296 NEONFormatDecoder nfd(instr);
7297 SimVRegister& rd = ReadVRegister(instr->GetRd());
7298 SimVRegister& rn = ReadVRegister(instr->GetRn());
7299 SimVRegister& rm = ReadVRegister(instr->GetRm());
7300
7301 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7302 switch (instr->Mask(NEON3SameFP16Mask)) {
7303#define SIM_FUNC(A, B) \
7304 case NEON_##A##_H: \
7305 B(vf, rd, rn, rm); \
7306 break;
7307 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007308 SIM_FUNC(FADD, fadd);
7309 SIM_FUNC(FMULX, fmulx);
7310 SIM_FUNC(FMAX, fmax);
7311 SIM_FUNC(FRECPS, frecps);
7312 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007313 SIM_FUNC(FSUB, fsub);
7314 SIM_FUNC(FMIN, fmin);
7315 SIM_FUNC(FRSQRTS, frsqrts);
7316 SIM_FUNC(FMAXNMP, fmaxnmp);
7317 SIM_FUNC(FADDP, faddp);
7318 SIM_FUNC(FMUL, fmul);
7319 SIM_FUNC(FMAXP, fmaxp);
7320 SIM_FUNC(FDIV, fdiv);
7321 SIM_FUNC(FMINNMP, fminnmp);
7322 SIM_FUNC(FABD, fabd);
7323 SIM_FUNC(FMINP, fminp);
7324#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08007325 case NEON_FMLA_H:
7326 fmla(vf, rd, rd, rn, rm);
7327 break;
7328 case NEON_FMLS_H:
7329 fmls(vf, rd, rd, rn, rm);
7330 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007331 case NEON_FCMEQ_H:
7332 fcmp(vf, rd, rn, rm, eq);
7333 break;
7334 case NEON_FCMGE_H:
7335 fcmp(vf, rd, rn, rm, ge);
7336 break;
7337 case NEON_FACGE_H:
7338 fabscmp(vf, rd, rn, rm, ge);
7339 break;
7340 case NEON_FCMGT_H:
7341 fcmp(vf, rd, rn, rm, gt);
7342 break;
7343 case NEON_FACGT_H:
7344 fabscmp(vf, rd, rn, rm, gt);
7345 break;
7346 default:
7347 VIXL_UNIMPLEMENTED();
7348 break;
7349 }
7350}
7351
Carey Williams2809e6c2018-03-13 12:24:16 +00007352void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7353 NEONFormatDecoder nfd(instr);
7354 SimVRegister& rd = ReadVRegister(instr->GetRd());
7355 SimVRegister& rn = ReadVRegister(instr->GetRn());
7356 SimVRegister& rm = ReadVRegister(instr->GetRm());
7357 int rot = 0;
7358 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01007359 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
7360 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01007361 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01007362 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
7363 rot = instr->GetImmRotFcadd();
7364 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01007365 } else {
7366 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01007367 case NEON_SDOT:
7368 sdot(vf, rd, rn, rm);
7369 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007370 case NEON_SQRDMLAH:
7371 sqrdmlah(vf, rd, rn, rm);
7372 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007373 case NEON_UDOT:
7374 udot(vf, rd, rn, rm);
7375 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007376 case NEON_SQRDMLSH:
7377 sqrdmlsh(vf, rd, rn, rm);
7378 break;
7379 default:
7380 VIXL_UNIMPLEMENTED();
7381 break;
7382 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007383 }
7384}
7385
7386
Alexandre Ramesd3832962016-07-04 15:03:43 +01007387void Simulator::VisitNEON3Different(const Instruction* instr) {
7388 NEONFormatDecoder nfd(instr);
7389 VectorFormat vf = nfd.GetVectorFormat();
7390 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7391
7392 SimVRegister& rd = ReadVRegister(instr->GetRd());
7393 SimVRegister& rn = ReadVRegister(instr->GetRn());
7394 SimVRegister& rm = ReadVRegister(instr->GetRm());
7395
7396 switch (instr->Mask(NEON3DifferentMask)) {
7397 case NEON_PMULL:
7398 pmull(vf_l, rd, rn, rm);
7399 break;
7400 case NEON_PMULL2:
7401 pmull2(vf_l, rd, rn, rm);
7402 break;
7403 case NEON_UADDL:
7404 uaddl(vf_l, rd, rn, rm);
7405 break;
7406 case NEON_UADDL2:
7407 uaddl2(vf_l, rd, rn, rm);
7408 break;
7409 case NEON_SADDL:
7410 saddl(vf_l, rd, rn, rm);
7411 break;
7412 case NEON_SADDL2:
7413 saddl2(vf_l, rd, rn, rm);
7414 break;
7415 case NEON_USUBL:
7416 usubl(vf_l, rd, rn, rm);
7417 break;
7418 case NEON_USUBL2:
7419 usubl2(vf_l, rd, rn, rm);
7420 break;
7421 case NEON_SSUBL:
7422 ssubl(vf_l, rd, rn, rm);
7423 break;
7424 case NEON_SSUBL2:
7425 ssubl2(vf_l, rd, rn, rm);
7426 break;
7427 case NEON_SABAL:
7428 sabal(vf_l, rd, rn, rm);
7429 break;
7430 case NEON_SABAL2:
7431 sabal2(vf_l, rd, rn, rm);
7432 break;
7433 case NEON_UABAL:
7434 uabal(vf_l, rd, rn, rm);
7435 break;
7436 case NEON_UABAL2:
7437 uabal2(vf_l, rd, rn, rm);
7438 break;
7439 case NEON_SABDL:
7440 sabdl(vf_l, rd, rn, rm);
7441 break;
7442 case NEON_SABDL2:
7443 sabdl2(vf_l, rd, rn, rm);
7444 break;
7445 case NEON_UABDL:
7446 uabdl(vf_l, rd, rn, rm);
7447 break;
7448 case NEON_UABDL2:
7449 uabdl2(vf_l, rd, rn, rm);
7450 break;
7451 case NEON_SMLAL:
7452 smlal(vf_l, rd, rn, rm);
7453 break;
7454 case NEON_SMLAL2:
7455 smlal2(vf_l, rd, rn, rm);
7456 break;
7457 case NEON_UMLAL:
7458 umlal(vf_l, rd, rn, rm);
7459 break;
7460 case NEON_UMLAL2:
7461 umlal2(vf_l, rd, rn, rm);
7462 break;
7463 case NEON_SMLSL:
7464 smlsl(vf_l, rd, rn, rm);
7465 break;
7466 case NEON_SMLSL2:
7467 smlsl2(vf_l, rd, rn, rm);
7468 break;
7469 case NEON_UMLSL:
7470 umlsl(vf_l, rd, rn, rm);
7471 break;
7472 case NEON_UMLSL2:
7473 umlsl2(vf_l, rd, rn, rm);
7474 break;
7475 case NEON_SMULL:
7476 smull(vf_l, rd, rn, rm);
7477 break;
7478 case NEON_SMULL2:
7479 smull2(vf_l, rd, rn, rm);
7480 break;
7481 case NEON_UMULL:
7482 umull(vf_l, rd, rn, rm);
7483 break;
7484 case NEON_UMULL2:
7485 umull2(vf_l, rd, rn, rm);
7486 break;
7487 case NEON_SQDMLAL:
7488 sqdmlal(vf_l, rd, rn, rm);
7489 break;
7490 case NEON_SQDMLAL2:
7491 sqdmlal2(vf_l, rd, rn, rm);
7492 break;
7493 case NEON_SQDMLSL:
7494 sqdmlsl(vf_l, rd, rn, rm);
7495 break;
7496 case NEON_SQDMLSL2:
7497 sqdmlsl2(vf_l, rd, rn, rm);
7498 break;
7499 case NEON_SQDMULL:
7500 sqdmull(vf_l, rd, rn, rm);
7501 break;
7502 case NEON_SQDMULL2:
7503 sqdmull2(vf_l, rd, rn, rm);
7504 break;
7505 case NEON_UADDW:
7506 uaddw(vf_l, rd, rn, rm);
7507 break;
7508 case NEON_UADDW2:
7509 uaddw2(vf_l, rd, rn, rm);
7510 break;
7511 case NEON_SADDW:
7512 saddw(vf_l, rd, rn, rm);
7513 break;
7514 case NEON_SADDW2:
7515 saddw2(vf_l, rd, rn, rm);
7516 break;
7517 case NEON_USUBW:
7518 usubw(vf_l, rd, rn, rm);
7519 break;
7520 case NEON_USUBW2:
7521 usubw2(vf_l, rd, rn, rm);
7522 break;
7523 case NEON_SSUBW:
7524 ssubw(vf_l, rd, rn, rm);
7525 break;
7526 case NEON_SSUBW2:
7527 ssubw2(vf_l, rd, rn, rm);
7528 break;
7529 case NEON_ADDHN:
7530 addhn(vf, rd, rn, rm);
7531 break;
7532 case NEON_ADDHN2:
7533 addhn2(vf, rd, rn, rm);
7534 break;
7535 case NEON_RADDHN:
7536 raddhn(vf, rd, rn, rm);
7537 break;
7538 case NEON_RADDHN2:
7539 raddhn2(vf, rd, rn, rm);
7540 break;
7541 case NEON_SUBHN:
7542 subhn(vf, rd, rn, rm);
7543 break;
7544 case NEON_SUBHN2:
7545 subhn2(vf, rd, rn, rm);
7546 break;
7547 case NEON_RSUBHN:
7548 rsubhn(vf, rd, rn, rm);
7549 break;
7550 case NEON_RSUBHN2:
7551 rsubhn2(vf, rd, rn, rm);
7552 break;
7553 default:
7554 VIXL_UNIMPLEMENTED();
7555 }
7556}
7557
7558
7559void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7560 NEONFormatDecoder nfd(instr);
7561
Jacob Bramleyca789742018-09-13 14:25:46 +01007562 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7563
Alexandre Ramesd3832962016-07-04 15:03:43 +01007564 SimVRegister& rd = ReadVRegister(instr->GetRd());
7565 SimVRegister& rn = ReadVRegister(instr->GetRn());
7566
Jacob Bramleyca789742018-09-13 14:25:46 +01007567 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7568 VectorFormat vf = nfd.GetVectorFormat(&map_half);
7569 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7570 case NEON_FMAXV_H:
7571 fmaxv(vf, rd, rn);
7572 break;
7573 case NEON_FMINV_H:
7574 fminv(vf, rd, rn);
7575 break;
7576 case NEON_FMAXNMV_H:
7577 fmaxnmv(vf, rd, rn);
7578 break;
7579 case NEON_FMINNMV_H:
7580 fminnmv(vf, rd, rn);
7581 break;
7582 default:
7583 VIXL_UNIMPLEMENTED();
7584 }
7585 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7586 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01007587 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7588
7589 switch (instr->Mask(NEONAcrossLanesFPMask)) {
7590 case NEON_FMAXV:
7591 fmaxv(vf, rd, rn);
7592 break;
7593 case NEON_FMINV:
7594 fminv(vf, rd, rn);
7595 break;
7596 case NEON_FMAXNMV:
7597 fmaxnmv(vf, rd, rn);
7598 break;
7599 case NEON_FMINNMV:
7600 fminnmv(vf, rd, rn);
7601 break;
7602 default:
7603 VIXL_UNIMPLEMENTED();
7604 }
7605 } else {
7606 VectorFormat vf = nfd.GetVectorFormat();
7607
7608 switch (instr->Mask(NEONAcrossLanesMask)) {
7609 case NEON_ADDV:
7610 addv(vf, rd, rn);
7611 break;
7612 case NEON_SMAXV:
7613 smaxv(vf, rd, rn);
7614 break;
7615 case NEON_SMINV:
7616 sminv(vf, rd, rn);
7617 break;
7618 case NEON_UMAXV:
7619 umaxv(vf, rd, rn);
7620 break;
7621 case NEON_UMINV:
7622 uminv(vf, rd, rn);
7623 break;
7624 case NEON_SADDLV:
7625 saddlv(vf, rd, rn);
7626 break;
7627 case NEON_UADDLV:
7628 uaddlv(vf, rd, rn);
7629 break;
7630 default:
7631 VIXL_UNIMPLEMENTED();
7632 }
7633 }
7634}
7635
7636
7637void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7638 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01007639 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007640 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01007641 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007642 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7643
7644 SimVRegister& rd = ReadVRegister(instr->GetRd());
7645 SimVRegister& rn = ReadVRegister(instr->GetRn());
7646
7647 ByElementOp Op = NULL;
7648
7649 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007650 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007651 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007652 int index_hlm = (index << 1) | instr->GetNEONM();
7653
7654 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
7655 // These are oddballs and are best handled as special cases.
7656 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
7657 // - The index is always H:L:M.
7658 case NEON_FMLAL_H_byelement:
7659 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7660 return;
7661 case NEON_FMLAL2_H_byelement:
7662 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7663 return;
7664 case NEON_FMLSL_H_byelement:
7665 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7666 return;
7667 case NEON_FMLSL2_H_byelement:
7668 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7669 return;
7670 }
7671
Alexandre Ramesd3832962016-07-04 15:03:43 +01007672 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007673 rm_reg = rm_low_reg;
7674 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007675 }
7676
7677 switch (instr->Mask(NEONByIndexedElementMask)) {
7678 case NEON_MUL_byelement:
7679 Op = &Simulator::mul;
7680 vf = vf_r;
7681 break;
7682 case NEON_MLA_byelement:
7683 Op = &Simulator::mla;
7684 vf = vf_r;
7685 break;
7686 case NEON_MLS_byelement:
7687 Op = &Simulator::mls;
7688 vf = vf_r;
7689 break;
7690 case NEON_SQDMULH_byelement:
7691 Op = &Simulator::sqdmulh;
7692 vf = vf_r;
7693 break;
7694 case NEON_SQRDMULH_byelement:
7695 Op = &Simulator::sqrdmulh;
7696 vf = vf_r;
7697 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007698 case NEON_SDOT_byelement:
7699 Op = &Simulator::sdot;
7700 vf = vf_r;
7701 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007702 case NEON_SQRDMLAH_byelement:
7703 Op = &Simulator::sqrdmlah;
7704 vf = vf_r;
7705 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007706 case NEON_UDOT_byelement:
7707 Op = &Simulator::udot;
7708 vf = vf_r;
7709 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007710 case NEON_SQRDMLSH_byelement:
7711 Op = &Simulator::sqrdmlsh;
7712 vf = vf_r;
7713 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007714 case NEON_SMULL_byelement:
7715 if (instr->Mask(NEON_Q)) {
7716 Op = &Simulator::smull2;
7717 } else {
7718 Op = &Simulator::smull;
7719 }
7720 break;
7721 case NEON_UMULL_byelement:
7722 if (instr->Mask(NEON_Q)) {
7723 Op = &Simulator::umull2;
7724 } else {
7725 Op = &Simulator::umull;
7726 }
7727 break;
7728 case NEON_SMLAL_byelement:
7729 if (instr->Mask(NEON_Q)) {
7730 Op = &Simulator::smlal2;
7731 } else {
7732 Op = &Simulator::smlal;
7733 }
7734 break;
7735 case NEON_UMLAL_byelement:
7736 if (instr->Mask(NEON_Q)) {
7737 Op = &Simulator::umlal2;
7738 } else {
7739 Op = &Simulator::umlal;
7740 }
7741 break;
7742 case NEON_SMLSL_byelement:
7743 if (instr->Mask(NEON_Q)) {
7744 Op = &Simulator::smlsl2;
7745 } else {
7746 Op = &Simulator::smlsl;
7747 }
7748 break;
7749 case NEON_UMLSL_byelement:
7750 if (instr->Mask(NEON_Q)) {
7751 Op = &Simulator::umlsl2;
7752 } else {
7753 Op = &Simulator::umlsl;
7754 }
7755 break;
7756 case NEON_SQDMULL_byelement:
7757 if (instr->Mask(NEON_Q)) {
7758 Op = &Simulator::sqdmull2;
7759 } else {
7760 Op = &Simulator::sqdmull;
7761 }
7762 break;
7763 case NEON_SQDMLAL_byelement:
7764 if (instr->Mask(NEON_Q)) {
7765 Op = &Simulator::sqdmlal2;
7766 } else {
7767 Op = &Simulator::sqdmlal;
7768 }
7769 break;
7770 case NEON_SQDMLSL_byelement:
7771 if (instr->Mask(NEON_Q)) {
7772 Op = &Simulator::sqdmlsl2;
7773 } else {
7774 Op = &Simulator::sqdmlsl;
7775 }
7776 break;
7777 default:
7778 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01007779 if (instr->GetFPType() == 0) {
7780 rm_reg &= 0xf;
7781 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7782 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007783 index = (index << 1) | instr->GetNEONL();
7784 }
7785
7786 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7787
7788 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01007789 case NEON_FMUL_H_byelement:
7790 vf = vf_half;
7791 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007792 case NEON_FMUL_byelement:
7793 Op = &Simulator::fmul;
7794 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007795 case NEON_FMLA_H_byelement:
7796 vf = vf_half;
7797 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007798 case NEON_FMLA_byelement:
7799 Op = &Simulator::fmla;
7800 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007801 case NEON_FMLS_H_byelement:
7802 vf = vf_half;
7803 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007804 case NEON_FMLS_byelement:
7805 Op = &Simulator::fmls;
7806 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007807 case NEON_FMULX_H_byelement:
7808 vf = vf_half;
7809 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007810 case NEON_FMULX_byelement:
7811 Op = &Simulator::fmulx;
7812 break;
7813 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007814 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00007815 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007816 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00007817 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007818 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007819 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
7820 case NEON_FCMLA_byelement:
7821 vf = vf_r;
7822 fcmla(vf,
7823 rd,
7824 rn,
7825 ReadVRegister(instr->GetRm()),
7826 index,
7827 instr->GetImmRotFcmlaSca());
7828 return;
7829 default:
7830 VIXL_UNIMPLEMENTED();
7831 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007832 }
7833 }
7834
7835 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
7836}
7837
7838
7839void Simulator::VisitNEONCopy(const Instruction* instr) {
7840 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7841 VectorFormat vf = nfd.GetVectorFormat();
7842
7843 SimVRegister& rd = ReadVRegister(instr->GetRd());
7844 SimVRegister& rn = ReadVRegister(instr->GetRn());
7845 int imm5 = instr->GetImmNEON5();
7846 int tz = CountTrailingZeros(imm5, 32);
7847 int reg_index = imm5 >> (tz + 1);
7848
7849 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7850 int imm4 = instr->GetImmNEON4();
7851 int rn_index = imm4 >> tz;
7852 ins_element(vf, rd, reg_index, rn, rn_index);
7853 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7854 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7855 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7856 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7857 value &= MaxUintFromFormat(vf);
7858 WriteXRegister(instr->GetRd(), value);
7859 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7860 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7861 if (instr->GetNEONQ()) {
7862 WriteXRegister(instr->GetRd(), value);
7863 } else {
7864 WriteWRegister(instr->GetRd(), (int32_t)value);
7865 }
7866 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7867 dup_element(vf, rd, rn, reg_index);
7868 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7869 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7870 } else {
7871 VIXL_UNIMPLEMENTED();
7872 }
7873}
7874
7875
7876void Simulator::VisitNEONExtract(const Instruction* instr) {
7877 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7878 VectorFormat vf = nfd.GetVectorFormat();
7879 SimVRegister& rd = ReadVRegister(instr->GetRd());
7880 SimVRegister& rn = ReadVRegister(instr->GetRn());
7881 SimVRegister& rm = ReadVRegister(instr->GetRm());
7882 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7883 int index = instr->GetImmNEONExt();
7884 ext(vf, rd, rn, rm, index);
7885 } else {
7886 VIXL_UNIMPLEMENTED();
7887 }
7888}
7889
7890
7891void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7892 AddrMode addr_mode) {
7893 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7894 VectorFormat vf = nfd.GetVectorFormat();
7895
7896 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7897 int reg_size = RegisterSizeInBytesFromFormat(vf);
7898
7899 int reg[4];
7900 uint64_t addr[4];
7901 for (int i = 0; i < 4; i++) {
7902 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7903 addr[i] = addr_base + (i * reg_size);
7904 }
Jacob Bramley423e5422019-11-13 19:15:55 +00007905 int struct_parts = 1;
7906 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007907 bool log_read = true;
7908
Martyn Capewell32009e32016-10-27 11:00:37 +01007909 // Bit 23 determines whether this is an offset or post-index addressing mode.
7910 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7911 // register or immediate in post-index mode.
7912 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007913 VIXL_UNREACHABLE();
7914 }
7915
7916 // We use the PostIndex mask here, as it works in this case for both Offset
7917 // and PostIndex addressing.
7918 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7919 case NEON_LD1_4v:
7920 case NEON_LD1_4v_post:
7921 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007922 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007923 VIXL_FALLTHROUGH();
7924 case NEON_LD1_3v:
7925 case NEON_LD1_3v_post:
7926 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007927 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007928 VIXL_FALLTHROUGH();
7929 case NEON_LD1_2v:
7930 case NEON_LD1_2v_post:
7931 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007932 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007933 VIXL_FALLTHROUGH();
7934 case NEON_LD1_1v:
7935 case NEON_LD1_1v_post:
7936 ld1(vf, ReadVRegister(reg[0]), addr[0]);
7937 break;
7938 case NEON_ST1_4v:
7939 case NEON_ST1_4v_post:
7940 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007941 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007942 VIXL_FALLTHROUGH();
7943 case NEON_ST1_3v:
7944 case NEON_ST1_3v_post:
7945 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007946 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007947 VIXL_FALLTHROUGH();
7948 case NEON_ST1_2v:
7949 case NEON_ST1_2v_post:
7950 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007951 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007952 VIXL_FALLTHROUGH();
7953 case NEON_ST1_1v:
7954 case NEON_ST1_1v_post:
7955 st1(vf, ReadVRegister(reg[0]), addr[0]);
7956 log_read = false;
7957 break;
7958 case NEON_LD2_post:
7959 case NEON_LD2:
7960 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007961 struct_parts = 2;
7962 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007963 break;
7964 case NEON_ST2:
7965 case NEON_ST2_post:
7966 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007967 struct_parts = 2;
7968 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01007969 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007970 break;
7971 case NEON_LD3_post:
7972 case NEON_LD3:
7973 ld3(vf,
7974 ReadVRegister(reg[0]),
7975 ReadVRegister(reg[1]),
7976 ReadVRegister(reg[2]),
7977 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007978 struct_parts = 3;
7979 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007980 break;
7981 case NEON_ST3:
7982 case NEON_ST3_post:
7983 st3(vf,
7984 ReadVRegister(reg[0]),
7985 ReadVRegister(reg[1]),
7986 ReadVRegister(reg[2]),
7987 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007988 struct_parts = 3;
7989 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01007990 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007991 break;
7992 case NEON_ST4:
7993 case NEON_ST4_post:
7994 st4(vf,
7995 ReadVRegister(reg[0]),
7996 ReadVRegister(reg[1]),
7997 ReadVRegister(reg[2]),
7998 ReadVRegister(reg[3]),
7999 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008000 struct_parts = 4;
8001 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01008002 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008003 break;
8004 case NEON_LD4_post:
8005 case NEON_LD4:
8006 ld4(vf,
8007 ReadVRegister(reg[0]),
8008 ReadVRegister(reg[1]),
8009 ReadVRegister(reg[2]),
8010 ReadVRegister(reg[3]),
8011 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008012 struct_parts = 4;
8013 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008014 break;
8015 default:
8016 VIXL_UNIMPLEMENTED();
8017 }
8018
Jacob Bramley7eb3e212019-11-22 17:28:05 +00008019 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00008020 if (do_trace) {
8021 PrintRegisterFormat print_format =
8022 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8023 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008024 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00008025 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01008026 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00008027 op = "->";
8028 // Stores don't represent a change to the source register's value, so only
8029 // print the relevant part of the value.
8030 print_format = GetPrintRegPartial(print_format);
8031 }
8032
8033 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
8034 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
8035 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
8036 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008037 }
8038 }
8039
8040 if (addr_mode == PostIndex) {
8041 int rm = instr->GetRm();
8042 // The immediate post index addressing mode is indicated by rm = 31.
8043 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00008044 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01008045 : ReadXRegister(rm);
8046 WriteXRegister(instr->GetRn(), addr_base);
8047 } else {
8048 VIXL_ASSERT(addr_mode == Offset);
8049 }
8050}
8051
8052
8053void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8054 NEONLoadStoreMultiStructHelper(instr, Offset);
8055}
8056
8057
8058void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8059 const Instruction* instr) {
8060 NEONLoadStoreMultiStructHelper(instr, PostIndex);
8061}
8062
8063
8064void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8065 AddrMode addr_mode) {
8066 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8067 int rt = instr->GetRt();
8068
Martyn Capewell32009e32016-10-27 11:00:37 +01008069 // Bit 23 determines whether this is an offset or post-index addressing mode.
8070 // In offset mode, bits 20 to 16 should be zero; these bits encode the
8071 // register or immediate in post-index mode.
8072 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008073 VIXL_UNREACHABLE();
8074 }
8075
8076 // We use the PostIndex mask here, as it works in this case for both Offset
8077 // and PostIndex addressing.
8078 bool do_load = false;
8079
Jacob Bramley423e5422019-11-13 19:15:55 +00008080 bool replicating = false;
8081
Alexandre Ramesd3832962016-07-04 15:03:43 +01008082 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8083 VectorFormat vf_t = nfd.GetVectorFormat();
8084
8085 VectorFormat vf = kFormat16B;
8086 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8087 case NEON_LD1_b:
8088 case NEON_LD1_b_post:
8089 case NEON_LD2_b:
8090 case NEON_LD2_b_post:
8091 case NEON_LD3_b:
8092 case NEON_LD3_b_post:
8093 case NEON_LD4_b:
8094 case NEON_LD4_b_post:
8095 do_load = true;
8096 VIXL_FALLTHROUGH();
8097 case NEON_ST1_b:
8098 case NEON_ST1_b_post:
8099 case NEON_ST2_b:
8100 case NEON_ST2_b_post:
8101 case NEON_ST3_b:
8102 case NEON_ST3_b_post:
8103 case NEON_ST4_b:
8104 case NEON_ST4_b_post:
8105 break;
8106
8107 case NEON_LD1_h:
8108 case NEON_LD1_h_post:
8109 case NEON_LD2_h:
8110 case NEON_LD2_h_post:
8111 case NEON_LD3_h:
8112 case NEON_LD3_h_post:
8113 case NEON_LD4_h:
8114 case NEON_LD4_h_post:
8115 do_load = true;
8116 VIXL_FALLTHROUGH();
8117 case NEON_ST1_h:
8118 case NEON_ST1_h_post:
8119 case NEON_ST2_h:
8120 case NEON_ST2_h_post:
8121 case NEON_ST3_h:
8122 case NEON_ST3_h_post:
8123 case NEON_ST4_h:
8124 case NEON_ST4_h_post:
8125 vf = kFormat8H;
8126 break;
8127 case NEON_LD1_s:
8128 case NEON_LD1_s_post:
8129 case NEON_LD2_s:
8130 case NEON_LD2_s_post:
8131 case NEON_LD3_s:
8132 case NEON_LD3_s_post:
8133 case NEON_LD4_s:
8134 case NEON_LD4_s_post:
8135 do_load = true;
8136 VIXL_FALLTHROUGH();
8137 case NEON_ST1_s:
8138 case NEON_ST1_s_post:
8139 case NEON_ST2_s:
8140 case NEON_ST2_s_post:
8141 case NEON_ST3_s:
8142 case NEON_ST3_s_post:
8143 case NEON_ST4_s:
8144 case NEON_ST4_s_post: {
8145 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8146 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8147 NEON_LD1_d_post);
8148 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8149 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8150 NEON_ST1_d_post);
8151 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8152 break;
8153 }
8154
8155 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008156 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008157 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008158 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008159 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008160 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008161 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008162 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008163 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008164 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00008165 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008166 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00008167
Alexandre Ramesd3832962016-07-04 15:03:43 +01008168 default:
8169 VIXL_UNIMPLEMENTED();
8170 }
8171
Alexandre Ramesd3832962016-07-04 15:03:43 +01008172 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8173 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00008174 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008175 int rt2 = (rt + 1) % kNumberOfVRegisters;
8176 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8177 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8178 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8179 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00008180 reg_count = 1;
8181 if (replicating) {
8182 VIXL_ASSERT(do_load);
8183 ld1r(vf, ReadVRegister(rt), addr);
8184 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008185 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008186 } else {
8187 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008188 }
8189 break;
8190 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00008191 reg_count = 2;
8192 if (replicating) {
8193 VIXL_ASSERT(do_load);
8194 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8195 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008196 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008197 } else {
8198 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008199 }
8200 break;
8201 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00008202 reg_count = 3;
8203 if (replicating) {
8204 VIXL_ASSERT(do_load);
8205 ld3r(vf,
8206 ReadVRegister(rt),
8207 ReadVRegister(rt2),
8208 ReadVRegister(rt3),
8209 addr);
8210 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008211 ld3(vf,
8212 ReadVRegister(rt),
8213 ReadVRegister(rt2),
8214 ReadVRegister(rt3),
8215 lane,
8216 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008217 } else {
8218 st3(vf,
8219 ReadVRegister(rt),
8220 ReadVRegister(rt2),
8221 ReadVRegister(rt3),
8222 lane,
8223 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008224 }
8225 break;
8226 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00008227 reg_count = 4;
8228 if (replicating) {
8229 VIXL_ASSERT(do_load);
8230 ld4r(vf,
8231 ReadVRegister(rt),
8232 ReadVRegister(rt2),
8233 ReadVRegister(rt3),
8234 ReadVRegister(rt4),
8235 addr);
8236 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008237 ld4(vf,
8238 ReadVRegister(rt),
8239 ReadVRegister(rt2),
8240 ReadVRegister(rt3),
8241 ReadVRegister(rt4),
8242 lane,
8243 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008244 } else {
8245 st4(vf,
8246 ReadVRegister(rt),
8247 ReadVRegister(rt2),
8248 ReadVRegister(rt3),
8249 ReadVRegister(rt4),
8250 lane,
8251 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008252 }
8253 break;
8254 default:
8255 VIXL_UNIMPLEMENTED();
8256 }
8257
Jacob Bramley423e5422019-11-13 19:15:55 +00008258 // Trace registers and/or memory writes.
8259 PrintRegisterFormat print_format =
8260 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8261 if (do_load) {
8262 if (ShouldTraceVRegs()) {
8263 if (replicating) {
8264 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8265 } else {
8266 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8267 }
8268 }
8269 } else {
8270 if (ShouldTraceWrites()) {
8271 // Stores don't represent a change to the source register's value, so only
8272 // print the relevant part of the value.
8273 print_format = GetPrintRegPartial(print_format);
8274 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8275 }
8276 }
8277
Alexandre Ramesd3832962016-07-04 15:03:43 +01008278 if (addr_mode == PostIndex) {
8279 int rm = instr->GetRm();
8280 int lane_size = LaneSizeInBytesFromFormat(vf);
8281 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00008282 addr + ((rm == 31) ? (reg_count * lane_size)
8283 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008284 }
8285}
8286
8287
8288void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8289 NEONLoadStoreSingleStructHelper(instr, Offset);
8290}
8291
8292
8293void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8294 const Instruction* instr) {
8295 NEONLoadStoreSingleStructHelper(instr, PostIndex);
8296}
8297
8298
8299void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8300 SimVRegister& rd = ReadVRegister(instr->GetRd());
8301 int cmode = instr->GetNEONCmode();
8302 int cmode_3_1 = (cmode >> 1) & 7;
8303 int cmode_3 = (cmode >> 3) & 1;
8304 int cmode_2 = (cmode >> 2) & 1;
8305 int cmode_1 = (cmode >> 1) & 1;
8306 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01008307 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008308 int q = instr->GetNEONQ();
8309 int op_bit = instr->GetNEONModImmOp();
8310 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01008311 // Find the format and immediate value
8312 uint64_t imm = 0;
8313 VectorFormat vform = kFormatUndefined;
8314 switch (cmode_3_1) {
8315 case 0x0:
8316 case 0x1:
8317 case 0x2:
8318 case 0x3:
8319 vform = (q == 1) ? kFormat4S : kFormat2S;
8320 imm = imm8 << (8 * cmode_3_1);
8321 break;
8322 case 0x4:
8323 case 0x5:
8324 vform = (q == 1) ? kFormat8H : kFormat4H;
8325 imm = imm8 << (8 * cmode_1);
8326 break;
8327 case 0x6:
8328 vform = (q == 1) ? kFormat4S : kFormat2S;
8329 if (cmode_0 == 0) {
8330 imm = imm8 << 8 | 0x000000ff;
8331 } else {
8332 imm = imm8 << 16 | 0x0000ffff;
8333 }
8334 break;
8335 case 0x7:
8336 if (cmode_0 == 0 && op_bit == 0) {
8337 vform = q ? kFormat16B : kFormat8B;
8338 imm = imm8;
8339 } else if (cmode_0 == 0 && op_bit == 1) {
8340 vform = q ? kFormat2D : kFormat1D;
8341 imm = 0;
8342 for (int i = 0; i < 8; ++i) {
8343 if (imm8 & (1 << i)) {
8344 imm |= (UINT64_C(0xff) << (8 * i));
8345 }
8346 }
8347 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01008348 if (half_enc == 1) {
8349 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01008350 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01008351 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008352 vform = q ? kFormat4S : kFormat2S;
8353 imm = FloatToRawbits(instr->GetImmNEONFP32());
8354 } else if (q == 1) {
8355 vform = kFormat2D;
8356 imm = DoubleToRawbits(instr->GetImmNEONFP64());
8357 } else {
8358 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8359 VisitUnallocated(instr);
8360 }
8361 }
8362 break;
8363 default:
8364 VIXL_UNREACHABLE();
8365 break;
8366 }
8367
8368 // Find the operation
8369 NEONModifiedImmediateOp op;
8370 if (cmode_3 == 0) {
8371 if (cmode_0 == 0) {
8372 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8373 } else { // cmode<0> == '1'
8374 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8375 }
8376 } else { // cmode<3> == '1'
8377 if (cmode_2 == 0) {
8378 if (cmode_0 == 0) {
8379 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8380 } else { // cmode<0> == '1'
8381 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8382 }
8383 } else { // cmode<2> == '1'
8384 if (cmode_1 == 0) {
8385 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8386 } else { // cmode<1> == '1'
8387 if (cmode_0 == 0) {
8388 op = NEONModifiedImmediate_MOVI;
8389 } else { // cmode<0> == '1'
8390 op = NEONModifiedImmediate_MOVI;
8391 }
8392 }
8393 }
8394 }
8395
8396 // Call the logic function
8397 if (op == NEONModifiedImmediate_ORR) {
8398 orr(vform, rd, rd, imm);
8399 } else if (op == NEONModifiedImmediate_BIC) {
8400 bic(vform, rd, rd, imm);
8401 } else if (op == NEONModifiedImmediate_MOVI) {
8402 movi(vform, rd, imm);
8403 } else if (op == NEONModifiedImmediate_MVNI) {
8404 mvni(vform, rd, imm);
8405 } else {
8406 VisitUnimplemented(instr);
8407 }
8408}
8409
8410
8411void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8412 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8413 VectorFormat vf = nfd.GetVectorFormat();
8414
8415 SimVRegister& rd = ReadVRegister(instr->GetRd());
8416 SimVRegister& rn = ReadVRegister(instr->GetRn());
8417
8418 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8419 // These instructions all use a two bit size field, except NOT and RBIT,
8420 // which use the field to encode the operation.
8421 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8422 case NEON_CMEQ_zero_scalar:
8423 cmp(vf, rd, rn, 0, eq);
8424 break;
8425 case NEON_CMGE_zero_scalar:
8426 cmp(vf, rd, rn, 0, ge);
8427 break;
8428 case NEON_CMGT_zero_scalar:
8429 cmp(vf, rd, rn, 0, gt);
8430 break;
8431 case NEON_CMLT_zero_scalar:
8432 cmp(vf, rd, rn, 0, lt);
8433 break;
8434 case NEON_CMLE_zero_scalar:
8435 cmp(vf, rd, rn, 0, le);
8436 break;
8437 case NEON_ABS_scalar:
8438 abs(vf, rd, rn);
8439 break;
8440 case NEON_SQABS_scalar:
8441 abs(vf, rd, rn).SignedSaturate(vf);
8442 break;
8443 case NEON_NEG_scalar:
8444 neg(vf, rd, rn);
8445 break;
8446 case NEON_SQNEG_scalar:
8447 neg(vf, rd, rn).SignedSaturate(vf);
8448 break;
8449 case NEON_SUQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008450 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008451 break;
8452 case NEON_USQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008453 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008454 break;
8455 default:
8456 VIXL_UNIMPLEMENTED();
8457 break;
8458 }
8459 } else {
8460 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8461 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8462
8463 // These instructions all use a one bit size field, except SQXTUN, SQXTN
8464 // and UQXTN, which use a two bit size field.
8465 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8466 case NEON_FRECPE_scalar:
8467 frecpe(fpf, rd, rn, fpcr_rounding);
8468 break;
8469 case NEON_FRECPX_scalar:
8470 frecpx(fpf, rd, rn);
8471 break;
8472 case NEON_FRSQRTE_scalar:
8473 frsqrte(fpf, rd, rn);
8474 break;
8475 case NEON_FCMGT_zero_scalar:
8476 fcmp_zero(fpf, rd, rn, gt);
8477 break;
8478 case NEON_FCMGE_zero_scalar:
8479 fcmp_zero(fpf, rd, rn, ge);
8480 break;
8481 case NEON_FCMEQ_zero_scalar:
8482 fcmp_zero(fpf, rd, rn, eq);
8483 break;
8484 case NEON_FCMLE_zero_scalar:
8485 fcmp_zero(fpf, rd, rn, le);
8486 break;
8487 case NEON_FCMLT_zero_scalar:
8488 fcmp_zero(fpf, rd, rn, lt);
8489 break;
8490 case NEON_SCVTF_scalar:
8491 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8492 break;
8493 case NEON_UCVTF_scalar:
8494 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8495 break;
8496 case NEON_FCVTNS_scalar:
8497 fcvts(fpf, rd, rn, FPTieEven);
8498 break;
8499 case NEON_FCVTNU_scalar:
8500 fcvtu(fpf, rd, rn, FPTieEven);
8501 break;
8502 case NEON_FCVTPS_scalar:
8503 fcvts(fpf, rd, rn, FPPositiveInfinity);
8504 break;
8505 case NEON_FCVTPU_scalar:
8506 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8507 break;
8508 case NEON_FCVTMS_scalar:
8509 fcvts(fpf, rd, rn, FPNegativeInfinity);
8510 break;
8511 case NEON_FCVTMU_scalar:
8512 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8513 break;
8514 case NEON_FCVTZS_scalar:
8515 fcvts(fpf, rd, rn, FPZero);
8516 break;
8517 case NEON_FCVTZU_scalar:
8518 fcvtu(fpf, rd, rn, FPZero);
8519 break;
8520 case NEON_FCVTAS_scalar:
8521 fcvts(fpf, rd, rn, FPTieAway);
8522 break;
8523 case NEON_FCVTAU_scalar:
8524 fcvtu(fpf, rd, rn, FPTieAway);
8525 break;
8526 case NEON_FCVTXN_scalar:
8527 // Unlike all of the other FP instructions above, fcvtxn encodes dest
8528 // size S as size<0>=1. There's only one case, so we ignore the form.
8529 VIXL_ASSERT(instr->ExtractBit(22) == 1);
8530 fcvtxn(kFormatS, rd, rn);
8531 break;
8532 default:
8533 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8534 case NEON_SQXTN_scalar:
8535 sqxtn(vf, rd, rn);
8536 break;
8537 case NEON_UQXTN_scalar:
8538 uqxtn(vf, rd, rn);
8539 break;
8540 case NEON_SQXTUN_scalar:
8541 sqxtun(vf, rd, rn);
8542 break;
8543 default:
8544 VIXL_UNIMPLEMENTED();
8545 }
8546 }
8547 }
8548}
8549
8550
Jacob Bramleyca789742018-09-13 14:25:46 +01008551void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8552 VectorFormat fpf = kFormatH;
8553 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8554
8555 SimVRegister& rd = ReadVRegister(instr->GetRd());
8556 SimVRegister& rn = ReadVRegister(instr->GetRn());
8557
8558 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8559 case NEON_FRECPE_H_scalar:
8560 frecpe(fpf, rd, rn, fpcr_rounding);
8561 break;
8562 case NEON_FRECPX_H_scalar:
8563 frecpx(fpf, rd, rn);
8564 break;
8565 case NEON_FRSQRTE_H_scalar:
8566 frsqrte(fpf, rd, rn);
8567 break;
8568 case NEON_FCMGT_H_zero_scalar:
8569 fcmp_zero(fpf, rd, rn, gt);
8570 break;
8571 case NEON_FCMGE_H_zero_scalar:
8572 fcmp_zero(fpf, rd, rn, ge);
8573 break;
8574 case NEON_FCMEQ_H_zero_scalar:
8575 fcmp_zero(fpf, rd, rn, eq);
8576 break;
8577 case NEON_FCMLE_H_zero_scalar:
8578 fcmp_zero(fpf, rd, rn, le);
8579 break;
8580 case NEON_FCMLT_H_zero_scalar:
8581 fcmp_zero(fpf, rd, rn, lt);
8582 break;
8583 case NEON_SCVTF_H_scalar:
8584 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8585 break;
8586 case NEON_UCVTF_H_scalar:
8587 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8588 break;
8589 case NEON_FCVTNS_H_scalar:
8590 fcvts(fpf, rd, rn, FPTieEven);
8591 break;
8592 case NEON_FCVTNU_H_scalar:
8593 fcvtu(fpf, rd, rn, FPTieEven);
8594 break;
8595 case NEON_FCVTPS_H_scalar:
8596 fcvts(fpf, rd, rn, FPPositiveInfinity);
8597 break;
8598 case NEON_FCVTPU_H_scalar:
8599 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8600 break;
8601 case NEON_FCVTMS_H_scalar:
8602 fcvts(fpf, rd, rn, FPNegativeInfinity);
8603 break;
8604 case NEON_FCVTMU_H_scalar:
8605 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8606 break;
8607 case NEON_FCVTZS_H_scalar:
8608 fcvts(fpf, rd, rn, FPZero);
8609 break;
8610 case NEON_FCVTZU_H_scalar:
8611 fcvtu(fpf, rd, rn, FPZero);
8612 break;
8613 case NEON_FCVTAS_H_scalar:
8614 fcvts(fpf, rd, rn, FPTieAway);
8615 break;
8616 case NEON_FCVTAU_H_scalar:
8617 fcvtu(fpf, rd, rn, FPTieAway);
8618 break;
8619 }
8620}
8621
8622
Alexandre Ramesd3832962016-07-04 15:03:43 +01008623void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8624 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8625 VectorFormat vf = nfd.GetVectorFormat();
8626
8627 SimVRegister& rd = ReadVRegister(instr->GetRd());
8628 SimVRegister& rn = ReadVRegister(instr->GetRn());
8629 SimVRegister& rm = ReadVRegister(instr->GetRm());
8630 switch (instr->Mask(NEONScalar3DiffMask)) {
8631 case NEON_SQDMLAL_scalar:
8632 sqdmlal(vf, rd, rn, rm);
8633 break;
8634 case NEON_SQDMLSL_scalar:
8635 sqdmlsl(vf, rd, rn, rm);
8636 break;
8637 case NEON_SQDMULL_scalar:
8638 sqdmull(vf, rd, rn, rm);
8639 break;
8640 default:
8641 VIXL_UNIMPLEMENTED();
8642 }
8643}
8644
8645
8646void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8647 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8648 VectorFormat vf = nfd.GetVectorFormat();
8649
8650 SimVRegister& rd = ReadVRegister(instr->GetRd());
8651 SimVRegister& rn = ReadVRegister(instr->GetRn());
8652 SimVRegister& rm = ReadVRegister(instr->GetRm());
8653
8654 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8655 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8656 switch (instr->Mask(NEONScalar3SameFPMask)) {
8657 case NEON_FMULX_scalar:
8658 fmulx(vf, rd, rn, rm);
8659 break;
8660 case NEON_FACGE_scalar:
8661 fabscmp(vf, rd, rn, rm, ge);
8662 break;
8663 case NEON_FACGT_scalar:
8664 fabscmp(vf, rd, rn, rm, gt);
8665 break;
8666 case NEON_FCMEQ_scalar:
8667 fcmp(vf, rd, rn, rm, eq);
8668 break;
8669 case NEON_FCMGE_scalar:
8670 fcmp(vf, rd, rn, rm, ge);
8671 break;
8672 case NEON_FCMGT_scalar:
8673 fcmp(vf, rd, rn, rm, gt);
8674 break;
8675 case NEON_FRECPS_scalar:
8676 frecps(vf, rd, rn, rm);
8677 break;
8678 case NEON_FRSQRTS_scalar:
8679 frsqrts(vf, rd, rn, rm);
8680 break;
8681 case NEON_FABD_scalar:
8682 fabd(vf, rd, rn, rm);
8683 break;
8684 default:
8685 VIXL_UNIMPLEMENTED();
8686 }
8687 } else {
8688 switch (instr->Mask(NEONScalar3SameMask)) {
8689 case NEON_ADD_scalar:
8690 add(vf, rd, rn, rm);
8691 break;
8692 case NEON_SUB_scalar:
8693 sub(vf, rd, rn, rm);
8694 break;
8695 case NEON_CMEQ_scalar:
8696 cmp(vf, rd, rn, rm, eq);
8697 break;
8698 case NEON_CMGE_scalar:
8699 cmp(vf, rd, rn, rm, ge);
8700 break;
8701 case NEON_CMGT_scalar:
8702 cmp(vf, rd, rn, rm, gt);
8703 break;
8704 case NEON_CMHI_scalar:
8705 cmp(vf, rd, rn, rm, hi);
8706 break;
8707 case NEON_CMHS_scalar:
8708 cmp(vf, rd, rn, rm, hs);
8709 break;
8710 case NEON_CMTST_scalar:
8711 cmptst(vf, rd, rn, rm);
8712 break;
8713 case NEON_USHL_scalar:
8714 ushl(vf, rd, rn, rm);
8715 break;
8716 case NEON_SSHL_scalar:
8717 sshl(vf, rd, rn, rm);
8718 break;
8719 case NEON_SQDMULH_scalar:
8720 sqdmulh(vf, rd, rn, rm);
8721 break;
8722 case NEON_SQRDMULH_scalar:
8723 sqrdmulh(vf, rd, rn, rm);
8724 break;
8725 case NEON_UQADD_scalar:
8726 add(vf, rd, rn, rm).UnsignedSaturate(vf);
8727 break;
8728 case NEON_SQADD_scalar:
8729 add(vf, rd, rn, rm).SignedSaturate(vf);
8730 break;
8731 case NEON_UQSUB_scalar:
8732 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8733 break;
8734 case NEON_SQSUB_scalar:
8735 sub(vf, rd, rn, rm).SignedSaturate(vf);
8736 break;
8737 case NEON_UQSHL_scalar:
8738 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8739 break;
8740 case NEON_SQSHL_scalar:
8741 sshl(vf, rd, rn, rm).SignedSaturate(vf);
8742 break;
8743 case NEON_URSHL_scalar:
8744 ushl(vf, rd, rn, rm).Round(vf);
8745 break;
8746 case NEON_SRSHL_scalar:
8747 sshl(vf, rd, rn, rm).Round(vf);
8748 break;
8749 case NEON_UQRSHL_scalar:
8750 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8751 break;
8752 case NEON_SQRSHL_scalar:
8753 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8754 break;
8755 default:
8756 VIXL_UNIMPLEMENTED();
8757 }
8758 }
8759}
8760
Jacob Bramleyca789742018-09-13 14:25:46 +01008761void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8762 SimVRegister& rd = ReadVRegister(instr->GetRd());
8763 SimVRegister& rn = ReadVRegister(instr->GetRn());
8764 SimVRegister& rm = ReadVRegister(instr->GetRm());
8765
8766 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8767 case NEON_FABD_H_scalar:
8768 fabd(kFormatH, rd, rn, rm);
8769 break;
8770 case NEON_FMULX_H_scalar:
8771 fmulx(kFormatH, rd, rn, rm);
8772 break;
8773 case NEON_FCMEQ_H_scalar:
8774 fcmp(kFormatH, rd, rn, rm, eq);
8775 break;
8776 case NEON_FCMGE_H_scalar:
8777 fcmp(kFormatH, rd, rn, rm, ge);
8778 break;
8779 case NEON_FCMGT_H_scalar:
8780 fcmp(kFormatH, rd, rn, rm, gt);
8781 break;
8782 case NEON_FACGE_H_scalar:
8783 fabscmp(kFormatH, rd, rn, rm, ge);
8784 break;
8785 case NEON_FACGT_H_scalar:
8786 fabscmp(kFormatH, rd, rn, rm, gt);
8787 break;
8788 case NEON_FRECPS_H_scalar:
8789 frecps(kFormatH, rd, rn, rm);
8790 break;
8791 case NEON_FRSQRTS_H_scalar:
8792 frsqrts(kFormatH, rd, rn, rm);
8793 break;
8794 default:
8795 VIXL_UNREACHABLE();
8796 }
8797}
8798
Alexandre Ramesd3832962016-07-04 15:03:43 +01008799
Alexander Gilday43785642018-04-04 13:42:33 +01008800void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8801 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8802 VectorFormat vf = nfd.GetVectorFormat();
8803
8804 SimVRegister& rd = ReadVRegister(instr->GetRd());
8805 SimVRegister& rn = ReadVRegister(instr->GetRn());
8806 SimVRegister& rm = ReadVRegister(instr->GetRm());
8807
8808 switch (instr->Mask(NEONScalar3SameExtraMask)) {
8809 case NEON_SQRDMLAH_scalar:
8810 sqrdmlah(vf, rd, rn, rm);
8811 break;
8812 case NEON_SQRDMLSH_scalar:
8813 sqrdmlsh(vf, rd, rn, rm);
8814 break;
8815 default:
8816 VIXL_UNIMPLEMENTED();
8817 }
8818}
8819
Alexandre Ramesd3832962016-07-04 15:03:43 +01008820void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8821 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8822 VectorFormat vf = nfd.GetVectorFormat();
8823 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8824
8825 SimVRegister& rd = ReadVRegister(instr->GetRd());
8826 SimVRegister& rn = ReadVRegister(instr->GetRn());
8827 ByElementOp Op = NULL;
8828
8829 int rm_reg = instr->GetRm();
8830 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8831 if (instr->GetNEONSize() == 1) {
8832 rm_reg &= 0xf;
8833 index = (index << 1) | instr->GetNEONM();
8834 }
8835
8836 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8837 case NEON_SQDMULL_byelement_scalar:
8838 Op = &Simulator::sqdmull;
8839 break;
8840 case NEON_SQDMLAL_byelement_scalar:
8841 Op = &Simulator::sqdmlal;
8842 break;
8843 case NEON_SQDMLSL_byelement_scalar:
8844 Op = &Simulator::sqdmlsl;
8845 break;
8846 case NEON_SQDMULH_byelement_scalar:
8847 Op = &Simulator::sqdmulh;
8848 vf = vf_r;
8849 break;
8850 case NEON_SQRDMULH_byelement_scalar:
8851 Op = &Simulator::sqrdmulh;
8852 vf = vf_r;
8853 break;
Alexander Gilday43785642018-04-04 13:42:33 +01008854 case NEON_SQRDMLAH_byelement_scalar:
8855 Op = &Simulator::sqrdmlah;
8856 vf = vf_r;
8857 break;
8858 case NEON_SQRDMLSH_byelement_scalar:
8859 Op = &Simulator::sqrdmlsh;
8860 vf = vf_r;
8861 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008862 default:
8863 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8864 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01008865 if (instr->GetFPType() == 0) {
8866 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8867 rm_reg &= 0xf;
8868 vf = kFormatH;
8869 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008870 index = (index << 1) | instr->GetNEONL();
8871 }
8872 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008873 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008874 case NEON_FMUL_byelement_scalar:
8875 Op = &Simulator::fmul;
8876 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008877 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008878 case NEON_FMLA_byelement_scalar:
8879 Op = &Simulator::fmla;
8880 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008881 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008882 case NEON_FMLS_byelement_scalar:
8883 Op = &Simulator::fmls;
8884 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008885 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008886 case NEON_FMULX_byelement_scalar:
8887 Op = &Simulator::fmulx;
8888 break;
8889 default:
8890 VIXL_UNIMPLEMENTED();
8891 }
8892 }
8893
8894 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8895}
8896
8897
8898void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8899 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8900 VectorFormat vf = nfd.GetVectorFormat();
8901
8902 SimVRegister& rd = ReadVRegister(instr->GetRd());
8903 SimVRegister& rn = ReadVRegister(instr->GetRn());
8904
8905 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8906 int imm5 = instr->GetImmNEON5();
8907 int tz = CountTrailingZeros(imm5, 32);
8908 int rn_index = imm5 >> (tz + 1);
8909 dup_element(vf, rd, rn, rn_index);
8910 } else {
8911 VIXL_UNIMPLEMENTED();
8912 }
8913}
8914
8915
8916void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008917 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008918 VectorFormat vf = nfd.GetVectorFormat();
8919
8920 SimVRegister& rd = ReadVRegister(instr->GetRd());
8921 SimVRegister& rn = ReadVRegister(instr->GetRn());
8922 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008923 case NEON_ADDP_scalar: {
8924 // All pairwise operations except ADDP use bit U to differentiate FP16
8925 // from FP32/FP64 variations.
8926 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8927 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008928 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008929 }
8930 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008931 case NEON_FADDP_scalar:
8932 faddp(vf, rd, rn);
8933 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008934 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008935 case NEON_FMAXP_scalar:
8936 fmaxp(vf, rd, rn);
8937 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008938 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008939 case NEON_FMAXNMP_scalar:
8940 fmaxnmp(vf, rd, rn);
8941 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008942 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008943 case NEON_FMINP_scalar:
8944 fminp(vf, rd, rn);
8945 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008946 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008947 case NEON_FMINNMP_scalar:
8948 fminnmp(vf, rd, rn);
8949 break;
8950 default:
8951 VIXL_UNIMPLEMENTED();
8952 }
8953}
8954
8955
8956void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
8957 SimVRegister& rd = ReadVRegister(instr->GetRd());
8958 SimVRegister& rn = ReadVRegister(instr->GetRn());
8959 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8960
8961 static const NEONFormatMap map = {{22, 21, 20, 19},
8962 {NF_UNDEF,
8963 NF_B,
8964 NF_H,
8965 NF_H,
8966 NF_S,
8967 NF_S,
8968 NF_S,
8969 NF_S,
8970 NF_D,
8971 NF_D,
8972 NF_D,
8973 NF_D,
8974 NF_D,
8975 NF_D,
8976 NF_D,
8977 NF_D}};
8978 NEONFormatDecoder nfd(instr, &map);
8979 VectorFormat vf = nfd.GetVectorFormat();
8980
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00008981 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
8982 int immh_immb = instr->GetImmNEONImmhImmb();
8983 int right_shift = (16 << highest_set_bit) - immh_immb;
8984 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008985 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
8986 case NEON_SHL_scalar:
8987 shl(vf, rd, rn, left_shift);
8988 break;
8989 case NEON_SLI_scalar:
8990 sli(vf, rd, rn, left_shift);
8991 break;
8992 case NEON_SQSHL_imm_scalar:
8993 sqshl(vf, rd, rn, left_shift);
8994 break;
8995 case NEON_UQSHL_imm_scalar:
8996 uqshl(vf, rd, rn, left_shift);
8997 break;
8998 case NEON_SQSHLU_scalar:
8999 sqshlu(vf, rd, rn, left_shift);
9000 break;
9001 case NEON_SRI_scalar:
9002 sri(vf, rd, rn, right_shift);
9003 break;
9004 case NEON_SSHR_scalar:
9005 sshr(vf, rd, rn, right_shift);
9006 break;
9007 case NEON_USHR_scalar:
9008 ushr(vf, rd, rn, right_shift);
9009 break;
9010 case NEON_SRSHR_scalar:
9011 sshr(vf, rd, rn, right_shift).Round(vf);
9012 break;
9013 case NEON_URSHR_scalar:
9014 ushr(vf, rd, rn, right_shift).Round(vf);
9015 break;
9016 case NEON_SSRA_scalar:
9017 ssra(vf, rd, rn, right_shift);
9018 break;
9019 case NEON_USRA_scalar:
9020 usra(vf, rd, rn, right_shift);
9021 break;
9022 case NEON_SRSRA_scalar:
9023 srsra(vf, rd, rn, right_shift);
9024 break;
9025 case NEON_URSRA_scalar:
9026 ursra(vf, rd, rn, right_shift);
9027 break;
9028 case NEON_UQSHRN_scalar:
9029 uqshrn(vf, rd, rn, right_shift);
9030 break;
9031 case NEON_UQRSHRN_scalar:
9032 uqrshrn(vf, rd, rn, right_shift);
9033 break;
9034 case NEON_SQSHRN_scalar:
9035 sqshrn(vf, rd, rn, right_shift);
9036 break;
9037 case NEON_SQRSHRN_scalar:
9038 sqrshrn(vf, rd, rn, right_shift);
9039 break;
9040 case NEON_SQSHRUN_scalar:
9041 sqshrun(vf, rd, rn, right_shift);
9042 break;
9043 case NEON_SQRSHRUN_scalar:
9044 sqrshrun(vf, rd, rn, right_shift);
9045 break;
9046 case NEON_FCVTZS_imm_scalar:
9047 fcvts(vf, rd, rn, FPZero, right_shift);
9048 break;
9049 case NEON_FCVTZU_imm_scalar:
9050 fcvtu(vf, rd, rn, FPZero, right_shift);
9051 break;
9052 case NEON_SCVTF_imm_scalar:
9053 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9054 break;
9055 case NEON_UCVTF_imm_scalar:
9056 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9057 break;
9058 default:
9059 VIXL_UNIMPLEMENTED();
9060 }
9061}
9062
9063
9064void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9065 SimVRegister& rd = ReadVRegister(instr->GetRd());
9066 SimVRegister& rn = ReadVRegister(instr->GetRn());
9067 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9068
9069 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9070 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9071 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01009072 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
9073 NF_4H, NF_8H, NF_4H, NF_8H,
9074 NF_2S, NF_4S, NF_2S, NF_4S,
9075 NF_2S, NF_4S, NF_2S, NF_4S,
9076 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9077 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9078 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9079 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01009080 NEONFormatDecoder nfd(instr, &map);
9081 VectorFormat vf = nfd.GetVectorFormat();
9082
9083 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9084 static const NEONFormatMap map_l =
9085 {{22, 21, 20, 19},
9086 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9087 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9088
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00009089 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9090 int immh_immb = instr->GetImmNEONImmhImmb();
9091 int right_shift = (16 << highest_set_bit) - immh_immb;
9092 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009093
9094 switch (instr->Mask(NEONShiftImmediateMask)) {
9095 case NEON_SHL:
9096 shl(vf, rd, rn, left_shift);
9097 break;
9098 case NEON_SLI:
9099 sli(vf, rd, rn, left_shift);
9100 break;
9101 case NEON_SQSHLU:
9102 sqshlu(vf, rd, rn, left_shift);
9103 break;
9104 case NEON_SRI:
9105 sri(vf, rd, rn, right_shift);
9106 break;
9107 case NEON_SSHR:
9108 sshr(vf, rd, rn, right_shift);
9109 break;
9110 case NEON_USHR:
9111 ushr(vf, rd, rn, right_shift);
9112 break;
9113 case NEON_SRSHR:
9114 sshr(vf, rd, rn, right_shift).Round(vf);
9115 break;
9116 case NEON_URSHR:
9117 ushr(vf, rd, rn, right_shift).Round(vf);
9118 break;
9119 case NEON_SSRA:
9120 ssra(vf, rd, rn, right_shift);
9121 break;
9122 case NEON_USRA:
9123 usra(vf, rd, rn, right_shift);
9124 break;
9125 case NEON_SRSRA:
9126 srsra(vf, rd, rn, right_shift);
9127 break;
9128 case NEON_URSRA:
9129 ursra(vf, rd, rn, right_shift);
9130 break;
9131 case NEON_SQSHL_imm:
9132 sqshl(vf, rd, rn, left_shift);
9133 break;
9134 case NEON_UQSHL_imm:
9135 uqshl(vf, rd, rn, left_shift);
9136 break;
9137 case NEON_SCVTF_imm:
9138 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9139 break;
9140 case NEON_UCVTF_imm:
9141 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9142 break;
9143 case NEON_FCVTZS_imm:
9144 fcvts(vf, rd, rn, FPZero, right_shift);
9145 break;
9146 case NEON_FCVTZU_imm:
9147 fcvtu(vf, rd, rn, FPZero, right_shift);
9148 break;
9149 case NEON_SSHLL:
9150 vf = vf_l;
9151 if (instr->Mask(NEON_Q)) {
9152 sshll2(vf, rd, rn, left_shift);
9153 } else {
9154 sshll(vf, rd, rn, left_shift);
9155 }
9156 break;
9157 case NEON_USHLL:
9158 vf = vf_l;
9159 if (instr->Mask(NEON_Q)) {
9160 ushll2(vf, rd, rn, left_shift);
9161 } else {
9162 ushll(vf, rd, rn, left_shift);
9163 }
9164 break;
9165 case NEON_SHRN:
9166 if (instr->Mask(NEON_Q)) {
9167 shrn2(vf, rd, rn, right_shift);
9168 } else {
9169 shrn(vf, rd, rn, right_shift);
9170 }
9171 break;
9172 case NEON_RSHRN:
9173 if (instr->Mask(NEON_Q)) {
9174 rshrn2(vf, rd, rn, right_shift);
9175 } else {
9176 rshrn(vf, rd, rn, right_shift);
9177 }
9178 break;
9179 case NEON_UQSHRN:
9180 if (instr->Mask(NEON_Q)) {
9181 uqshrn2(vf, rd, rn, right_shift);
9182 } else {
9183 uqshrn(vf, rd, rn, right_shift);
9184 }
9185 break;
9186 case NEON_UQRSHRN:
9187 if (instr->Mask(NEON_Q)) {
9188 uqrshrn2(vf, rd, rn, right_shift);
9189 } else {
9190 uqrshrn(vf, rd, rn, right_shift);
9191 }
9192 break;
9193 case NEON_SQSHRN:
9194 if (instr->Mask(NEON_Q)) {
9195 sqshrn2(vf, rd, rn, right_shift);
9196 } else {
9197 sqshrn(vf, rd, rn, right_shift);
9198 }
9199 break;
9200 case NEON_SQRSHRN:
9201 if (instr->Mask(NEON_Q)) {
9202 sqrshrn2(vf, rd, rn, right_shift);
9203 } else {
9204 sqrshrn(vf, rd, rn, right_shift);
9205 }
9206 break;
9207 case NEON_SQSHRUN:
9208 if (instr->Mask(NEON_Q)) {
9209 sqshrun2(vf, rd, rn, right_shift);
9210 } else {
9211 sqshrun(vf, rd, rn, right_shift);
9212 }
9213 break;
9214 case NEON_SQRSHRUN:
9215 if (instr->Mask(NEON_Q)) {
9216 sqrshrun2(vf, rd, rn, right_shift);
9217 } else {
9218 sqrshrun(vf, rd, rn, right_shift);
9219 }
9220 break;
9221 default:
9222 VIXL_UNIMPLEMENTED();
9223 }
9224}
9225
9226
9227void Simulator::VisitNEONTable(const Instruction* instr) {
9228 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9229 VectorFormat vf = nfd.GetVectorFormat();
9230
9231 SimVRegister& rd = ReadVRegister(instr->GetRd());
9232 SimVRegister& rn = ReadVRegister(instr->GetRn());
9233 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9234 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9235 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9236 SimVRegister& rm = ReadVRegister(instr->GetRm());
9237
9238 switch (instr->Mask(NEONTableMask)) {
9239 case NEON_TBL_1v:
9240 tbl(vf, rd, rn, rm);
9241 break;
9242 case NEON_TBL_2v:
9243 tbl(vf, rd, rn, rn2, rm);
9244 break;
9245 case NEON_TBL_3v:
9246 tbl(vf, rd, rn, rn2, rn3, rm);
9247 break;
9248 case NEON_TBL_4v:
9249 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9250 break;
9251 case NEON_TBX_1v:
9252 tbx(vf, rd, rn, rm);
9253 break;
9254 case NEON_TBX_2v:
9255 tbx(vf, rd, rn, rn2, rm);
9256 break;
9257 case NEON_TBX_3v:
9258 tbx(vf, rd, rn, rn2, rn3, rm);
9259 break;
9260 case NEON_TBX_4v:
9261 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9262 break;
9263 default:
9264 VIXL_UNIMPLEMENTED();
9265 }
9266}
9267
9268
9269void Simulator::VisitNEONPerm(const Instruction* instr) {
9270 NEONFormatDecoder nfd(instr);
9271 VectorFormat vf = nfd.GetVectorFormat();
9272
9273 SimVRegister& rd = ReadVRegister(instr->GetRd());
9274 SimVRegister& rn = ReadVRegister(instr->GetRn());
9275 SimVRegister& rm = ReadVRegister(instr->GetRm());
9276
9277 switch (instr->Mask(NEONPermMask)) {
9278 case NEON_TRN1:
9279 trn1(vf, rd, rn, rm);
9280 break;
9281 case NEON_TRN2:
9282 trn2(vf, rd, rn, rm);
9283 break;
9284 case NEON_UZP1:
9285 uzp1(vf, rd, rn, rm);
9286 break;
9287 case NEON_UZP2:
9288 uzp2(vf, rd, rn, rm);
9289 break;
9290 case NEON_ZIP1:
9291 zip1(vf, rd, rn, rm);
9292 break;
9293 case NEON_ZIP2:
9294 zip2(vf, rd, rn, rm);
9295 break;
9296 default:
9297 VIXL_UNIMPLEMENTED();
9298 }
9299}
9300
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009301void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00009302 SimVRegister& zd = ReadVRegister(instr->GetRd());
9303 SimVRegister& zn = ReadVRegister(instr->GetRn());
9304 SimVRegister& zm = ReadVRegister(instr->GetRm());
9305 SimVRegister temp;
9306
9307 VectorFormat vform = kFormatVnD;
9308 mov(vform, temp, zm);
9309
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009310 switch (instr->Mask(SVEAddressGenerationMask)) {
9311 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009312 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009313 break;
9314 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009315 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009316 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00009317 case ADR_z_az_s_same_scaled:
9318 vform = kFormatVnS;
9319 break;
9320 case ADR_z_az_d_same_scaled:
9321 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009322 break;
9323 default:
9324 VIXL_UNIMPLEMENTED();
9325 break;
9326 }
Martyn Capewell48522f52020-03-16 15:31:19 +00009327
9328 int shift_amount = instr->ExtractBits(11, 10);
9329 shl(vform, temp, temp, shift_amount);
9330 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009331}
9332
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009333void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9334 const Instruction* instr) {
9335 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07009336 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009337 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009338 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07009339 case ORR_z_zi: {
9340 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9341 uint64_t imm = instr->GetSVEImmLogical();
9342 // Valid immediate is a non-zero bits
9343 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009344 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9345 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07009346 SVEFormatFromLaneSizeInBytesLog2(lane_size),
9347 ReadVRegister(instr->GetRd()),
9348 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009349 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07009350 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009351 default:
9352 VIXL_UNIMPLEMENTED();
9353 break;
9354 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009355}
9356
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009357void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9358 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9359 case DUPM_z_i: {
9360 /* DUPM uses the same lane size and immediate encoding as bitwise logical
9361 * immediate instructions. */
9362 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9363 uint64_t imm = instr->GetSVEImmLogical();
9364 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9365 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9366 break;
9367 }
9368 default:
9369 VIXL_UNIMPLEMENTED();
9370 break;
9371 }
9372}
9373
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009374void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07009375 SimVRegister& zd = ReadVRegister(instr->GetRd());
9376 SimVRegister& zn = ReadVRegister(instr->GetRn());
9377 SimVRegister& zm = ReadVRegister(instr->GetRm());
9378 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9379
TatWai Chong13634762019-07-16 16:20:45 -07009380 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07009381 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009382 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009383 logical_op = AND;
9384 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009385 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009386 logical_op = BIC;
9387 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009388 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009389 logical_op = EOR;
9390 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07009391 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009392 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009393 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009394 default:
TatWai Chong13634762019-07-16 16:20:45 -07009395 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009396 VIXL_UNIMPLEMENTED();
9397 break;
9398 }
TatWai Chong13634762019-07-16 16:20:45 -07009399 // Lane size of registers is irrelevant to the bitwise operations, so perform
9400 // the operation on D-sized lanes.
9401 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009402}
9403
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009404void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00009405 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9406 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9407
9408 SimVRegister scratch;
9409 SimVRegister result;
9410
9411 bool for_division = false;
9412 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009413 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009414 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009415 shift_op = ASR;
9416 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009417 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009418 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009419 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009420 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009421 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009422 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009423 break;
9424 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009425 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009426 break;
9427 default:
9428 VIXL_UNIMPLEMENTED();
9429 break;
9430 }
Martyn Capewell83e86612020-02-19 15:46:15 +00009431
9432 std::pair<int, int> shift_and_lane_size =
9433 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9434 unsigned lane_size = shift_and_lane_size.second;
9435 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9436 int shift_dist = shift_and_lane_size.first;
9437
9438 if ((shift_op == ASR) && for_division) {
9439 asrd(vform, result, zdn, shift_dist);
9440 } else {
9441 if (shift_op == LSL) {
9442 // Shift distance is computed differently for LSL. Convert the result.
9443 shift_dist = (8 << lane_size) - shift_dist;
9444 }
9445 dup_immediate(vform, scratch, shift_dist);
9446 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9447 }
9448 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009449}
9450
9451void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9452 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009453 VectorFormat vform = instr->GetSVEVectorFormat();
9454 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9455 SimVRegister& zm = ReadVRegister(instr->GetRn());
9456 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell76c094a2020-02-13 17:26:49 +00009457 SimVRegister result;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009458
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009459 // SVE uses the whole (saturated) lane for the shift amount.
9460 bool shift_in_ls_byte = false;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009461
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009462 switch (form_hash_) {
9463 case Hash("asrr_z_p_zz"):
9464 sshr(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009465 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009466 case Hash("asr_z_p_zz"):
9467 sshr(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009468 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009469 case Hash("lslr_z_p_zz"):
9470 sshl(vform, result, zm, zdn, shift_in_ls_byte);
9471 break;
9472 case Hash("lsl_z_p_zz"):
9473 sshl(vform, result, zdn, zm, shift_in_ls_byte);
9474 break;
9475 case Hash("lsrr_z_p_zz"):
9476 ushr(vform, result, zm, zdn);
9477 break;
9478 case Hash("lsr_z_p_zz"):
9479 ushr(vform, result, zdn, zm);
9480 break;
9481 case Hash("sqrshl_z_p_zz"):
9482 sshl(vform, result, zdn, zm, shift_in_ls_byte)
9483 .Round(vform)
9484 .SignedSaturate(vform);
9485 break;
9486 case Hash("sqrshlr_z_p_zz"):
9487 sshl(vform, result, zm, zdn, shift_in_ls_byte)
9488 .Round(vform)
9489 .SignedSaturate(vform);
9490 break;
9491 case Hash("sqshl_z_p_zz"):
9492 sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
9493 break;
9494 case Hash("sqshlr_z_p_zz"):
9495 sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
9496 break;
9497 case Hash("srshl_z_p_zz"):
9498 sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9499 break;
9500 case Hash("srshlr_z_p_zz"):
9501 sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9502 break;
9503 case Hash("uqrshl_z_p_zz"):
9504 ushl(vform, result, zdn, zm, shift_in_ls_byte)
9505 .Round(vform)
9506 .UnsignedSaturate(vform);
9507 break;
9508 case Hash("uqrshlr_z_p_zz"):
9509 ushl(vform, result, zm, zdn, shift_in_ls_byte)
9510 .Round(vform)
9511 .UnsignedSaturate(vform);
9512 break;
9513 case Hash("uqshl_z_p_zz"):
9514 ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
9515 break;
9516 case Hash("uqshlr_z_p_zz"):
9517 ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
9518 break;
9519 case Hash("urshl_z_p_zz"):
9520 ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9521 break;
9522 case Hash("urshlr_z_p_zz"):
9523 ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009524 break;
9525 default:
9526 VIXL_UNIMPLEMENTED();
9527 break;
9528 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009529 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009530}
9531
9532void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9533 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009534 VectorFormat vform = instr->GetSVEVectorFormat();
9535 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9536 SimVRegister& zm = ReadVRegister(instr->GetRn());
9537 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9538
9539 SimVRegister result;
9540 Shift shift_op = ASR;
9541
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009542 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9543 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009544 break;
9545 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009546 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009547 break;
9548 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009549 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009550 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009551 default:
9552 VIXL_UNIMPLEMENTED();
9553 break;
9554 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009555 SVEBitwiseShiftHelper(shift_op,
9556 vform,
9557 result,
9558 zdn,
9559 zm,
9560 /* is_wide_elements = */ true);
9561 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009562}
9563
9564void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08009565 SimVRegister& zd = ReadVRegister(instr->GetRd());
9566 SimVRegister& zn = ReadVRegister(instr->GetRn());
9567
9568 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009569 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9570 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009571 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009572 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009573 break;
9574 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009575 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009576 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009577 break;
9578 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08009579 case LSR_z_zw:
9580 shift_op = LSR;
9581 break;
9582 default:
9583 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009584 VIXL_UNIMPLEMENTED();
9585 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08009586 }
9587
9588 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9589 case ASR_z_zi:
9590 case LSL_z_zi:
9591 case LSR_z_zi: {
9592 SimVRegister scratch;
9593 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00009594 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08009595 unsigned lane_size = shift_and_lane_size.second;
9596 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9597 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00009598 int shift_dist = shift_and_lane_size.first;
9599 if (shift_op == LSL) {
9600 // Shift distance is computed differently for LSL. Convert the result.
9601 shift_dist = (8 << lane_size) - shift_dist;
9602 }
9603 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08009604 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9605 break;
9606 }
9607 case ASR_z_zw:
9608 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009609 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009610 SVEBitwiseShiftHelper(shift_op,
9611 instr->GetSVEVectorFormat(),
9612 zd,
9613 zn,
9614 ReadVRegister(instr->GetRm()),
9615 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009616 break;
9617 default:
9618 VIXL_UNIMPLEMENTED();
9619 break;
9620 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009621}
9622
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009623void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00009624 // Although the instructions have a separate encoding class, the lane size is
9625 // encoded in the same way as most other SVE instructions.
9626 VectorFormat vform = instr->GetSVEVectorFormat();
9627
9628 int pattern = instr->GetImmSVEPredicateConstraint();
9629 int count = GetPredicateConstraintLaneCount(vform, pattern);
9630 int multiplier = instr->ExtractBits(19, 16) + 1;
9631
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009632 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009633 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009634 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009635 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009636 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009637 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009638 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009639 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009640 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009641 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009642 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009643 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009644 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009645 default:
9646 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00009647 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009648 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00009649
9650 WriteXRegister(instr->GetRd(),
9651 IncDecN(ReadXRegister(instr->GetRd()),
9652 count * multiplier,
9653 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009654}
9655
9656void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009657 VectorFormat vform = instr->GetSVEVectorFormat();
9658 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9659 VIXL_UNIMPLEMENTED();
9660 }
9661
9662 int pattern = instr->GetImmSVEPredicateConstraint();
9663 int count = GetPredicateConstraintLaneCount(vform, pattern);
9664 int multiplier = instr->ExtractBits(19, 16) + 1;
9665
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009666 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9667 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009668 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009669 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009670 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009671 break;
9672 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009673 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009674 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009675 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009676 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009677 default:
9678 VIXL_UNIMPLEMENTED();
9679 break;
9680 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009681
9682 SimVRegister& zd = ReadVRegister(instr->GetRd());
9683 SimVRegister scratch;
9684 dup_immediate(vform,
9685 scratch,
9686 IncDecN(0,
9687 count * multiplier,
9688 LaneSizeInBitsFromFormat(vform)));
9689 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009690}
9691
9692void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9693 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009694 // Although the instructions have a separate encoding class, the lane size is
9695 // encoded in the same way as most other SVE instructions.
9696 VectorFormat vform = instr->GetSVEVectorFormat();
9697
9698 int pattern = instr->GetImmSVEPredicateConstraint();
9699 int count = GetPredicateConstraintLaneCount(vform, pattern);
9700 int multiplier = instr->ExtractBits(19, 16) + 1;
9701
9702 unsigned width = kXRegSize;
9703 bool is_signed = false;
9704
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009705 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009706 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009707 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009708 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009709 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009710 width = kWRegSize;
9711 VIXL_FALLTHROUGH();
9712 case SQDECB_r_rs_x:
9713 case SQDECD_r_rs_x:
9714 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009715 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009716 is_signed = true;
9717 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009718 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009719 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009720 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009721 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009722 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009723 width = kWRegSize;
9724 VIXL_FALLTHROUGH();
9725 case SQINCB_r_rs_x:
9726 case SQINCD_r_rs_x:
9727 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009728 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009729 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009730 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009731 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009732 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009733 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009734 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009735 width = kWRegSize;
9736 VIXL_FALLTHROUGH();
9737 case UQDECB_r_rs_x:
9738 case UQDECD_r_rs_x:
9739 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009740 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009741 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009742 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009743 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009744 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009745 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009746 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009747 width = kWRegSize;
9748 VIXL_FALLTHROUGH();
9749 case UQINCB_r_rs_x:
9750 case UQINCD_r_rs_x:
9751 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009752 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009753 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009754 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009755 default:
9756 VIXL_UNIMPLEMENTED();
9757 break;
9758 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009759
9760 WriteXRegister(instr->GetRd(),
9761 IncDecN(ReadXRegister(instr->GetRd()),
9762 count * multiplier,
9763 width,
9764 true,
9765 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009766}
9767
9768void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9769 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009770 VectorFormat vform = instr->GetSVEVectorFormat();
9771 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9772 VIXL_UNIMPLEMENTED();
9773 }
9774
9775 int pattern = instr->GetImmSVEPredicateConstraint();
9776 int count = GetPredicateConstraintLaneCount(vform, pattern);
9777 int multiplier = instr->ExtractBits(19, 16) + 1;
9778
9779 SimVRegister& zd = ReadVRegister(instr->GetRd());
9780 SimVRegister scratch;
9781 dup_immediate(vform,
9782 scratch,
9783 IncDecN(0,
9784 count * multiplier,
9785 LaneSizeInBitsFromFormat(vform)));
9786
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009787 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9788 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009789 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009790 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009791 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009792 break;
9793 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009794 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009795 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009796 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009797 break;
9798 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009799 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009800 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009801 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009802 break;
9803 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009804 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009805 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009806 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009807 break;
9808 default:
9809 VIXL_UNIMPLEMENTED();
9810 break;
9811 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009812}
9813
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009814void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009815 switch (instr->Mask(SVEElementCountMask)) {
9816 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009817 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009818 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009819 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00009820 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009821 break;
9822 default:
9823 VIXL_UNIMPLEMENTED();
9824 break;
9825 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00009826
9827 // Although the instructions are separated, the lane size is encoded in the
9828 // same way as most other SVE instructions.
9829 VectorFormat vform = instr->GetSVEVectorFormat();
9830
9831 int pattern = instr->GetImmSVEPredicateConstraint();
9832 int count = GetPredicateConstraintLaneCount(vform, pattern);
9833 int multiplier = instr->ExtractBits(19, 16) + 1;
9834 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009835}
9836
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009837void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009838 VectorFormat vform = instr->GetSVEVectorFormat();
9839 SimVRegister& vdn = ReadVRegister(instr->GetRd());
9840 SimVRegister& zm = ReadVRegister(instr->GetRn());
9841 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9842
Martyn Capewell310a0822020-09-08 20:09:17 +01009843 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9844
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009845 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9846 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009847 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009848 break;
9849 default:
9850 VIXL_UNIMPLEMENTED();
9851 break;
9852 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009853}
9854
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009855void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07009856 VectorFormat vform = instr->GetSVEVectorFormat();
9857 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9858 SimVRegister& zm = ReadVRegister(instr->GetRn());
9859 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9860
Martyn Capewell310a0822020-09-08 20:09:17 +01009861 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
TatWai Chongd316c5e2019-10-16 12:22:10 -07009862
Martyn Capewell310a0822020-09-08 20:09:17 +01009863 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009864 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009865 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009866 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009867 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009868 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009869 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009870 break;
9871 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009872 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009873 break;
9874 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009875 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009876 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009877 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009878 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009879 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009880 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009881 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009882 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009883 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009884 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009885 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009886 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009887 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009888 break;
9889 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009890 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009891 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009892 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009893 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009894 break;
9895 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009896 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009897 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009898 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009899 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009900 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009901 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009902 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009903 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009904 default:
9905 VIXL_UNIMPLEMENTED();
9906 break;
9907 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07009908 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009909}
9910
9911void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9912 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00009913 VectorFormat vform = instr->GetSVEVectorFormat();
9914 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9915 VIXL_UNIMPLEMENTED();
9916 }
9917
9918 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9919 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9920 SimVRegister result;
9921
9922 int i1 = instr->ExtractBit(5);
9923 SimVRegister add_sub_imm, min_max_imm, mul_imm;
9924 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9925 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9926 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9927 dup_immediate(vform, add_sub_imm, i1 ? one : half);
9928 dup_immediate(vform, min_max_imm, i1 ? one : 0);
9929 dup_immediate(vform, mul_imm, i1 ? two : half);
9930
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009931 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9932 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009933 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009934 break;
9935 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009936 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009937 break;
9938 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009939 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009940 break;
9941 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009942 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009943 break;
9944 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009945 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009946 break;
9947 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009948 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009949 break;
9950 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009951 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009952 break;
9953 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009954 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009955 break;
9956 default:
9957 VIXL_UNIMPLEMENTED();
9958 break;
9959 }
Martyn Capewella2fadc22020-01-16 16:09:55 +00009960 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009961}
9962
9963void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009964 VectorFormat vform = instr->GetSVEVectorFormat();
9965 SimVRegister& zd = ReadVRegister(instr->GetRd());
9966 SimVRegister& zm = ReadVRegister(instr->GetRn());
9967
Martyn Capewell310a0822020-09-08 20:09:17 +01009968 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9969
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009970 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009971 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009972 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009973 break;
9974 default:
9975 VIXL_UNIMPLEMENTED();
9976 break;
9977 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009978}
9979
9980void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -07009981 VectorFormat vform = instr->GetSVEVectorFormat();
9982 SimVRegister& zd = ReadVRegister(instr->GetRd());
9983 SimVRegister& zn = ReadVRegister(instr->GetRn());
9984 SimVRegister& zm = ReadVRegister(instr->GetRm());
9985
Martyn Capewell310a0822020-09-08 20:09:17 +01009986 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9987
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009988 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
9989 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009990 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009991 break;
9992 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009993 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009994 break;
9995 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009996 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009997 break;
9998 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009999 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010000 break;
10001 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -070010002 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010003 break;
10004 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010005 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010006 break;
10007 default:
10008 VIXL_UNIMPLEMENTED();
10009 break;
10010 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010011}
10012
10013void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -080010014 SimPRegister& pd = ReadPRegister(instr->GetPd());
10015 SimVRegister& zn = ReadVRegister(instr->GetRn());
10016 SimVRegister& zm = ReadVRegister(instr->GetRm());
10017 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10018 VectorFormat vform = instr->GetSVEVectorFormat();
10019 SimVRegister result;
10020
Martyn Capewell310a0822020-09-08 20:09:17 +010010021 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10022
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010023 switch (instr->Mask(SVEFPCompareVectorsMask)) {
10024 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010025 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010026 break;
10027 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010028 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010029 break;
10030 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010031 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010032 break;
10033 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010034 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010035 break;
10036 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010037 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010038 break;
10039 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010040 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010041 break;
10042 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010043 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010044 break;
10045 default:
10046 VIXL_UNIMPLEMENTED();
10047 break;
10048 }
TatWai Chong47c26842020-02-10 01:51:32 -080010049
10050 ExtractFromSimVRegister(vform, pd, result);
10051 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010052}
10053
10054void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -080010055 SimPRegister& pd = ReadPRegister(instr->GetPd());
10056 SimVRegister& zn = ReadVRegister(instr->GetRn());
10057 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10058 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chonge3775132020-02-16 22:13:17 -080010059
Martyn Capewell310a0822020-09-08 20:09:17 +010010060 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10061
10062 SimVRegister result;
TatWai Chonge3775132020-02-16 22:13:17 -080010063 SimVRegister zeros;
10064 dup_immediate(kFormatVnD, zeros, 0);
10065
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010066 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10067 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010068 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010069 break;
10070 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010071 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010072 break;
10073 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010074 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010075 break;
10076 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010077 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010078 break;
10079 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010080 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010081 break;
10082 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010083 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010084 break;
10085 default:
10086 VIXL_UNIMPLEMENTED();
10087 break;
10088 }
TatWai Chonge3775132020-02-16 22:13:17 -080010089
10090 ExtractFromSimVRegister(vform, pd, result);
10091 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010092}
10093
10094void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010095 VectorFormat vform = instr->GetSVEVectorFormat();
10096
10097 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10098 VIXL_UNIMPLEMENTED();
10099 }
10100
10101 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10102 SimVRegister& zm = ReadVRegister(instr->GetRn());
10103 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10104 int rot = instr->ExtractBit(16);
10105
10106 SimVRegister result;
10107
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010108 switch (instr->Mask(SVEFPComplexAdditionMask)) {
10109 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010110 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010111 break;
10112 default:
10113 VIXL_UNIMPLEMENTED();
10114 break;
10115 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010116 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010117}
10118
10119void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +010010120 VectorFormat vform = instr->GetSVEVectorFormat();
10121
10122 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10123 VIXL_UNIMPLEMENTED();
10124 }
10125
10126 SimVRegister& zda = ReadVRegister(instr->GetRd());
10127 SimVRegister& zn = ReadVRegister(instr->GetRn());
10128 SimVRegister& zm = ReadVRegister(instr->GetRm());
10129 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10130 int rot = instr->ExtractBits(14, 13);
10131
10132 SimVRegister result;
10133
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010134 switch (instr->Mask(SVEFPComplexMulAddMask)) {
10135 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +010010136 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010137 break;
10138 default:
10139 VIXL_UNIMPLEMENTED();
10140 break;
10141 }
Martyn Capewell75f1c432020-03-30 09:23:27 +010010142 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010143}
10144
10145void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +010010146 SimVRegister& zda = ReadVRegister(instr->GetRd());
10147 SimVRegister& zn = ReadVRegister(instr->GetRn());
10148 int rot = instr->ExtractBits(11, 10);
10149 unsigned zm_code = instr->GetRm();
10150 int index = -1;
10151 VectorFormat vform, vform_dup;
10152
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010153 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10154 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010155 vform = kFormatVnH;
10156 vform_dup = kFormatVnS;
10157 index = zm_code >> 3;
10158 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010159 break;
10160 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010161 vform = kFormatVnS;
10162 vform_dup = kFormatVnD;
10163 index = zm_code >> 4;
10164 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010165 break;
10166 default:
10167 VIXL_UNIMPLEMENTED();
10168 break;
10169 }
Martyn Capewelle4886e52020-03-30 09:28:52 +010010170
10171 if (index >= 0) {
10172 SimVRegister temp;
10173 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10174 fcmla(vform, zda, zn, temp, zda, rot);
10175 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010176}
10177
Martyn Capewell894962f2020-02-05 15:46:44 +000010178typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10179 LogicVRegister dst,
10180 const LogicVRegister& src);
10181
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010182void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +000010183 VectorFormat vform = instr->GetSVEVectorFormat();
10184 SimVRegister& vd = ReadVRegister(instr->GetRd());
10185 SimVRegister& zn = ReadVRegister(instr->GetRn());
10186 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10187 int lane_size = LaneSizeInBitsFromFormat(vform);
10188
10189 uint64_t inactive_value = 0;
10190 FastReduceFn fn = nullptr;
10191
Martyn Capewell310a0822020-09-08 20:09:17 +010010192 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10193
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010194 switch (instr->Mask(SVEFPFastReductionMask)) {
10195 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010196 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010197 break;
10198 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010199 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10200 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010201 break;
10202 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010203 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10204 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010205 break;
10206 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010207 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10208 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010209 break;
10210 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010211 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10212 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010213 break;
10214 default:
10215 VIXL_UNIMPLEMENTED();
10216 break;
10217 }
Martyn Capewell894962f2020-02-05 15:46:44 +000010218
10219 SimVRegister scratch;
10220 dup_immediate(vform, scratch, inactive_value);
10221 mov_merging(vform, scratch, pg, zn);
10222 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010223}
10224
10225void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +000010226 VectorFormat vform = kFormatUndefined;
10227 unsigned zm_code = instr->GetRm() & 0xf;
10228 unsigned index = instr->ExtractBits(20, 19);
10229
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010230 switch (instr->Mask(SVEFPMulIndexMask)) {
10231 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010232 vform = kFormatVnD;
10233 index >>= 1; // Only bit 20 is the index for D lanes.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010234 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010235 case FMUL_z_zzi_h_i3h:
10236 index += 4; // Bit 22 (i3h) is the top bit of index.
10237 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010238 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010239 vform = kFormatVnH;
10240 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010241 break;
10242 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010243 vform = kFormatVnS;
10244 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010245 break;
10246 default:
10247 VIXL_UNIMPLEMENTED();
10248 break;
10249 }
Martyn Capewell50e9f552020-01-07 17:45:03 +000010250
10251 SimVRegister& zd = ReadVRegister(instr->GetRd());
10252 SimVRegister& zn = ReadVRegister(instr->GetRn());
10253 SimVRegister temp;
10254
Martyn Capewell46352612020-07-02 15:47:54 +010010255 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
Martyn Capewell50e9f552020-01-07 17:45:03 +000010256 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010257}
10258
10259void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -080010260 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongf8d29f12020-02-16 22:53:18 -080010261 SimVRegister& zd = ReadVRegister(instr->GetRd());
10262 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10263 SimVRegister result;
10264
Martyn Capewell310a0822020-09-08 20:09:17 +010010265 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10266
TatWai Chongf8d29f12020-02-16 22:53:18 -080010267 if (instr->ExtractBit(15) == 0) {
10268 // Floating-point multiply-accumulate writing addend.
10269 SimVRegister& zm = ReadVRegister(instr->GetRm());
10270 SimVRegister& zn = ReadVRegister(instr->GetRn());
10271
10272 switch (instr->Mask(SVEFPMulAddMask)) {
10273 // zda = zda + zn * zm
10274 case FMLA_z_p_zzz:
10275 fmla(vform, result, zd, zn, zm);
10276 break;
10277 // zda = -zda + -zn * zm
10278 case FNMLA_z_p_zzz:
10279 fneg(vform, result, zd);
10280 fmls(vform, result, result, zn, zm);
10281 break;
10282 // zda = zda + -zn * zm
10283 case FMLS_z_p_zzz:
10284 fmls(vform, result, zd, zn, zm);
10285 break;
10286 // zda = -zda + zn * zm
10287 case FNMLS_z_p_zzz:
10288 fneg(vform, result, zd);
10289 fmla(vform, result, result, zn, zm);
10290 break;
10291 default:
10292 VIXL_UNIMPLEMENTED();
10293 break;
10294 }
10295 } else {
10296 // Floating-point multiply-accumulate writing multiplicand.
10297 SimVRegister& za = ReadVRegister(instr->GetRm());
10298 SimVRegister& zm = ReadVRegister(instr->GetRn());
10299
10300 switch (instr->Mask(SVEFPMulAddMask)) {
10301 // zdn = za + zdn * zm
10302 case FMAD_z_p_zzz:
10303 fmla(vform, result, za, zd, zm);
10304 break;
10305 // zdn = -za + -zdn * zm
10306 case FNMAD_z_p_zzz:
10307 fneg(vform, result, za);
10308 fmls(vform, result, result, zd, zm);
10309 break;
10310 // zdn = za + -zdn * zm
10311 case FMSB_z_p_zzz:
10312 fmls(vform, result, za, zd, zm);
10313 break;
10314 // zdn = -za + zdn * zm
10315 case FNMSB_z_p_zzz:
10316 fneg(vform, result, za);
10317 fmla(vform, result, result, zd, zm);
10318 break;
10319 default:
10320 VIXL_UNIMPLEMENTED();
10321 break;
10322 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010323 }
TatWai Chongf8d29f12020-02-16 22:53:18 -080010324
10325 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010326}
10327
10328void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010329 VectorFormat vform = kFormatUndefined;
10330 unsigned zm_code = 0xffffffff;
10331 unsigned index = 0xffffffff;
10332
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010333 switch (instr->Mask(SVEFPMulAddIndexMask)) {
10334 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010335 case FMLS_z_zzzi_d:
10336 vform = kFormatVnD;
10337 zm_code = instr->GetRmLow16();
10338 // Only bit 20 is the index for D lanes.
10339 index = instr->ExtractBit(20);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010340 break;
10341 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010342 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010343 vform = kFormatVnS;
10344 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
10345 index = instr->ExtractBits(20, 19);
10346 break;
10347 case FMLA_z_zzzi_h:
10348 case FMLS_z_zzzi_h:
10349 case FMLA_z_zzzi_h_i3h:
10350 case FMLS_z_zzzi_h_i3h:
10351 vform = kFormatVnH;
10352 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
10353 index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010354 break;
10355 default:
10356 VIXL_UNIMPLEMENTED();
10357 break;
10358 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010359
10360 SimVRegister& zd = ReadVRegister(instr->GetRd());
10361 SimVRegister& zn = ReadVRegister(instr->GetRn());
10362 SimVRegister temp;
10363
Martyn Capewellc7501512020-03-16 10:35:33 +000010364 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010365 if (instr->ExtractBit(10) == 1) {
10366 fmls(vform, zd, zd, zn, temp);
10367 } else {
10368 fmla(vform, zd, zd, zn, temp);
10369 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010370}
10371
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010372void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -080010373 SimVRegister& zd = ReadVRegister(instr->GetRd());
10374 SimVRegister& zn = ReadVRegister(instr->GetRn());
10375 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10376 int dst_data_size;
10377 int src_data_size;
10378
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010379 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010380 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010381 case FCVTZU_z_p_z_d2w:
10382 dst_data_size = kSRegSize;
10383 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010384 break;
10385 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010386 case FCVTZU_z_p_z_d2x:
10387 dst_data_size = kDRegSize;
10388 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010389 break;
10390 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010391 case FCVTZU_z_p_z_fp162h:
10392 dst_data_size = kHRegSize;
10393 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010394 break;
10395 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010396 case FCVTZU_z_p_z_fp162w:
10397 dst_data_size = kSRegSize;
10398 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010399 break;
10400 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010401 case FCVTZU_z_p_z_fp162x:
10402 dst_data_size = kDRegSize;
10403 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010404 break;
10405 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010406 case FCVTZU_z_p_z_s2w:
10407 dst_data_size = kSRegSize;
10408 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010409 break;
10410 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010411 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010412 dst_data_size = kDRegSize;
10413 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010414 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010415 default:
10416 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -080010417 dst_data_size = 0;
10418 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010419 break;
10420 }
TatWai Chongdb7437c2020-01-09 17:44:10 -080010421
10422 VectorFormat vform =
10423 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -080010424
10425 if (instr->ExtractBit(16) == 0) {
10426 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10427 } else {
10428 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10429 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010430}
10431
10432void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -080010433 SimVRegister& zd = ReadVRegister(instr->GetRd());
10434 SimVRegister& zn = ReadVRegister(instr->GetRn());
10435 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10436 int dst_data_size;
10437 int src_data_size;
10438
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010439 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010440 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010441 dst_data_size = kHRegSize;
10442 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010443 break;
10444 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010445 dst_data_size = kSRegSize;
10446 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010447 break;
10448 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010449 dst_data_size = kDRegSize;
10450 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010451 break;
10452 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010453 dst_data_size = kSRegSize;
10454 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010455 break;
10456 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010457 dst_data_size = kDRegSize;
10458 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010459 break;
10460 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010461 dst_data_size = kHRegSize;
10462 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010463 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010464 default:
10465 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -080010466 dst_data_size = 0;
10467 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010468 break;
10469 }
TatWai Chong2cb1b612020-03-04 23:51:21 -080010470 VectorFormat vform =
10471 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10472
10473 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010474}
10475
10476void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010477 SimVRegister& zd = ReadVRegister(instr->GetRd());
10478 SimVRegister& zn = ReadVRegister(instr->GetRn());
10479 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10480 VectorFormat vform = instr->GetSVEVectorFormat();
10481 SimVRegister result;
10482
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010483 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010484 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010485 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010486 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010487 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -080010488 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010489 break;
10490 default:
10491 VIXL_UNIMPLEMENTED();
10492 break;
10493 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010494 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010495}
10496
10497void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010498 SimVRegister& zd = ReadVRegister(instr->GetRd());
10499 SimVRegister& zn = ReadVRegister(instr->GetRn());
10500 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10501 VectorFormat vform = instr->GetSVEVectorFormat();
10502 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10503 bool exact_exception = false;
10504
Martyn Capewell310a0822020-09-08 20:09:17 +010010505 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10506
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010507 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010508 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010509 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010510 break;
10511 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010512 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010513 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010514 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010515 break;
10516 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010517 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010518 break;
10519 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010520 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010521 break;
10522 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010523 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010524 break;
10525 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010526 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010527 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010528 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010529 VIXL_UNIMPLEMENTED();
10530 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010531 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010532
10533 SimVRegister result;
10534 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10535 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010536}
10537
10538void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -080010539 SimVRegister& zd = ReadVRegister(instr->GetRd());
10540 SimVRegister& zn = ReadVRegister(instr->GetRn());
10541 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10542 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10543 int dst_data_size;
10544 int src_data_size;
10545
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010546 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010547 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010548 case UCVTF_z_p_z_h2fp16:
10549 dst_data_size = kHRegSize;
10550 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010551 break;
10552 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010553 case UCVTF_z_p_z_w2d:
10554 dst_data_size = kDRegSize;
10555 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010556 break;
10557 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010558 case UCVTF_z_p_z_w2fp16:
10559 dst_data_size = kHRegSize;
10560 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010561 break;
10562 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010563 case UCVTF_z_p_z_w2s:
10564 dst_data_size = kSRegSize;
10565 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010566 break;
10567 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010568 case UCVTF_z_p_z_x2d:
10569 dst_data_size = kDRegSize;
10570 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010571 break;
10572 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010573 case UCVTF_z_p_z_x2fp16:
10574 dst_data_size = kHRegSize;
10575 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010576 break;
10577 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010578 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010579 dst_data_size = kSRegSize;
10580 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010581 break;
10582 default:
10583 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -080010584 dst_data_size = 0;
10585 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010586 break;
10587 }
TatWai Chong31cd6a02020-01-10 13:03:26 -080010588
10589 VectorFormat vform =
10590 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10591
10592 if (instr->ExtractBit(16) == 0) {
10593 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10594 } else {
10595 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10596 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010597}
10598
10599void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +000010600 VectorFormat vform = instr->GetSVEVectorFormat();
10601 SimVRegister& zd = ReadVRegister(instr->GetRd());
10602 SimVRegister& zn = ReadVRegister(instr->GetRn());
10603 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10604
Martyn Capewell310a0822020-09-08 20:09:17 +010010605 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10606
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010607 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10608 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010609 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010610 break;
10611 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010612 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010613 break;
10614 default:
10615 VIXL_UNIMPLEMENTED();
10616 break;
10617 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010618}
10619
10620void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010621 VectorFormat vform = instr->GetSVEVectorFormat();
10622 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10623
10624 int count = CountActiveLanes(vform, pg);
10625
10626 if (instr->ExtractBit(11) == 0) {
10627 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10628 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10629 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010630 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010631 break;
10632 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010633 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010634 break;
10635 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010636 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010637 break;
10638 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010639 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010640 break;
10641 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010642 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010643 break;
10644 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010645 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010646 break;
10647 default:
10648 VIXL_UNIMPLEMENTED();
10649 break;
10650 }
10651 } else {
10652 bool is_saturating = (instr->ExtractBit(18) == 0);
10653 bool decrement =
10654 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10655 bool is_signed = (instr->ExtractBit(16) == 0);
10656 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10657 unsigned width = sf ? kXRegSize : kWRegSize;
10658
10659 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10660 case DECP_r_p_r:
10661 case INCP_r_p_r:
10662 case SQDECP_r_p_r_sx:
10663 case SQDECP_r_p_r_x:
10664 case SQINCP_r_p_r_sx:
10665 case SQINCP_r_p_r_x:
10666 case UQDECP_r_p_r_uw:
10667 case UQDECP_r_p_r_x:
10668 case UQINCP_r_p_r_uw:
10669 case UQINCP_r_p_r_x:
10670 WriteXRegister(instr->GetRd(),
10671 IncDecN(ReadXRegister(instr->GetRd()),
10672 decrement ? -count : count,
10673 width,
10674 is_saturating,
10675 is_signed));
10676 break;
10677 default:
10678 VIXL_UNIMPLEMENTED();
10679 break;
10680 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010681 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010682}
10683
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010684uint64_t Simulator::IncDecN(uint64_t acc,
10685 int64_t delta,
10686 unsigned n,
10687 bool is_saturating,
10688 bool is_signed) {
10689 VIXL_ASSERT(n <= 64);
10690 VIXL_ASSERT(IsIntN(n, delta));
10691
10692 uint64_t sign_mask = UINT64_C(1) << (n - 1);
10693 uint64_t mask = GetUintMask(n);
10694
10695 acc &= mask; // Ignore initial accumulator high bits.
10696 uint64_t result = (acc + delta) & mask;
10697
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010698 bool result_negative = ((result & sign_mask) != 0);
10699
10700 if (is_saturating) {
10701 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +000010702 bool acc_negative = ((acc & sign_mask) != 0);
10703 bool delta_negative = delta < 0;
10704
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010705 // If the signs of the operands are the same, but different from the
10706 // result, there was an overflow.
10707 if ((acc_negative == delta_negative) &&
10708 (acc_negative != result_negative)) {
10709 if (result_negative) {
10710 // Saturate to [..., INT<n>_MAX].
10711 result_negative = false;
10712 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
10713 } else {
10714 // Saturate to [INT<n>_MIN, ...].
10715 result_negative = true;
10716 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
10717 }
10718 }
10719 } else {
10720 if ((delta < 0) && (result > acc)) {
10721 // Saturate to [0, ...].
10722 result = 0;
10723 } else if ((delta > 0) && (result < acc)) {
10724 // Saturate to [..., UINT<n>_MAX].
10725 result = mask;
10726 }
10727 }
10728 }
10729
10730 // Sign-extend if necessary.
10731 if (result_negative && is_signed) result |= ~mask;
10732
10733 return result;
10734}
10735
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010736void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010737 VectorFormat vform = instr->GetSVEVectorFormat();
10738 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010739 switch (instr->Mask(SVEIndexGenerationMask)) {
10740 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010741 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010742 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010743 case INDEX_z_rr: {
10744 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10745 : instr->ExtractSignedBits(9, 5);
10746 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10747 : instr->ExtractSignedBits(20, 16);
10748 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010749 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010750 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010751 default:
10752 VIXL_UNIMPLEMENTED();
10753 break;
10754 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010755}
10756
10757void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -070010758 VectorFormat vform = instr->GetSVEVectorFormat();
10759 SimVRegister& zd = ReadVRegister(instr->GetRd());
10760 SimVRegister& zn = ReadVRegister(instr->GetRn());
10761 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010762 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10763 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010764 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010765 break;
10766 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010767 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010768 break;
10769 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010770 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010771 break;
10772 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010773 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010774 break;
10775 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010776 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010777 break;
10778 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010779 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010780 break;
10781 default:
10782 VIXL_UNIMPLEMENTED();
10783 break;
10784 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010785}
10786
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010787void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010788 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -070010789 VectorFormat vform = instr->GetSVEVectorFormat();
10790 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10791 SimVRegister& zm = ReadVRegister(instr->GetRn());
10792 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10793 SimVRegister result;
10794
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010795 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010796 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010797 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010798 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010799 case SUBR_z_p_zz:
10800 sub(vform, result, zm, zdn);
10801 break;
10802 case SUB_z_p_zz:
10803 sub(vform, result, zdn, zm);
10804 break;
10805 default:
10806 VIXL_UNIMPLEMENTED();
10807 break;
10808 }
10809 mov_merging(vform, zdn, pg, result);
10810}
10811
10812void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10813 VectorFormat vform = instr->GetSVEVectorFormat();
10814 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10815 SimVRegister& zm = ReadVRegister(instr->GetRn());
10816 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10817 SimVRegister result;
10818
10819 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010820 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010821 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010822 break;
10823 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010824 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010825 break;
10826 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010827 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010828 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010829 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010830 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010831 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010832 default:
10833 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010834 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010835 }
10836 mov_merging(vform, zdn, pg, result);
10837}
10838
10839void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10840 VectorFormat vform = instr->GetSVEVectorFormat();
10841 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10842 SimVRegister& zm = ReadVRegister(instr->GetRn());
10843 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10844 SimVRegister result;
10845
10846 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10847 case MUL_z_p_zz:
10848 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010849 break;
10850 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010851 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010852 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010853 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010854 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010855 break;
10856 default:
10857 VIXL_UNIMPLEMENTED();
10858 break;
10859 }
TatWai Chong13634762019-07-16 16:20:45 -070010860 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010861}
10862
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010863void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10864 const Instruction* instr) {
10865 VectorFormat vform = instr->GetSVEVectorFormat();
10866 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10867 SimVRegister& zm = ReadVRegister(instr->GetRn());
10868 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10869 SimVRegister result;
10870
10871 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10872 case SABD_z_p_zz:
10873 absdiff(vform, result, zdn, zm, true);
10874 break;
10875 case SMAX_z_p_zz:
10876 smax(vform, result, zdn, zm);
10877 break;
10878 case SMIN_z_p_zz:
10879 smin(vform, result, zdn, zm);
10880 break;
10881 case UABD_z_p_zz:
10882 absdiff(vform, result, zdn, zm, false);
10883 break;
10884 case UMAX_z_p_zz:
10885 umax(vform, result, zdn, zm);
10886 break;
10887 case UMIN_z_p_zz:
10888 umin(vform, result, zdn, zm);
10889 break;
10890 default:
10891 VIXL_UNIMPLEMENTED();
10892 break;
10893 }
10894 mov_merging(vform, zdn, pg, result);
10895}
10896
10897void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10898 VectorFormat vform = instr->GetSVEVectorFormat();
10899 SimVRegister& zd = ReadVRegister(instr->GetRd());
10900 SimVRegister scratch;
10901
10902 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10903 case MUL_z_zi:
10904 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10905 mul(vform, zd, zd, scratch);
10906 break;
10907 default:
10908 VIXL_UNIMPLEMENTED();
10909 break;
10910 }
10911}
10912
10913void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10914 VectorFormat vform = instr->GetSVEVectorFormat();
10915 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10916 SimVRegister& zm = ReadVRegister(instr->GetRn());
10917 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10918 SimVRegister result;
10919
10920 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10921
10922 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10923 case SDIVR_z_p_zz:
10924 sdiv(vform, result, zm, zdn);
10925 break;
10926 case SDIV_z_p_zz:
10927 sdiv(vform, result, zdn, zm);
10928 break;
10929 case UDIVR_z_p_zz:
10930 udiv(vform, result, zm, zdn);
10931 break;
10932 case UDIV_z_p_zz:
10933 udiv(vform, result, zdn, zm);
10934 break;
10935 default:
10936 VIXL_UNIMPLEMENTED();
10937 break;
10938 }
10939 mov_merging(vform, zdn, pg, result);
10940}
10941
10942void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10943 VectorFormat vform = instr->GetSVEVectorFormat();
10944 SimVRegister& zd = ReadVRegister(instr->GetRd());
10945 SimVRegister scratch;
10946
10947 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10948 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10949
10950 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10951 case SMAX_z_zi:
10952 dup_immediate(vform, scratch, signed_imm);
10953 smax(vform, zd, zd, scratch);
10954 break;
10955 case SMIN_z_zi:
10956 dup_immediate(vform, scratch, signed_imm);
10957 smin(vform, zd, zd, scratch);
10958 break;
10959 case UMAX_z_zi:
10960 dup_immediate(vform, scratch, unsigned_imm);
10961 umax(vform, zd, zd, scratch);
10962 break;
10963 case UMIN_z_zi:
10964 dup_immediate(vform, scratch, unsigned_imm);
10965 umin(vform, zd, zd, scratch);
10966 break;
10967 default:
10968 VIXL_UNIMPLEMENTED();
10969 break;
10970 }
10971}
10972
10973void Simulator::VisitSVEIntCompareScalarCountAndLimit(
10974 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -070010975 unsigned rn_code = instr->GetRn();
10976 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010977 SimPRegister& pd = ReadPRegister(instr->GetPd());
10978 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongc844bb22019-06-10 15:32:53 -070010979
Martyn Capewellf0844012020-10-23 16:38:26 +010010980 bool is_64_bit = instr->ExtractBit(12) == 1;
10981 int rsize = is_64_bit ? kXRegSize : kWRegSize;
10982 uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
10983
10984 uint64_t usrc1 = ReadXRegister(rn_code);
10985 int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
10986 uint64_t usrc2 = ssrc2 & mask;
10987
10988 bool reverse = (form_hash_ == Hash("whilege_p_p_rr")) ||
10989 (form_hash_ == Hash("whilegt_p_p_rr")) ||
10990 (form_hash_ == Hash("whilehi_p_p_rr")) ||
10991 (form_hash_ == Hash("whilehs_p_p_rr"));
10992
10993 int lane_count = LaneCountFromFormat(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010994 bool last = true;
Martyn Capewellf0844012020-10-23 16:38:26 +010010995 for (int i = 0; i < lane_count; i++) {
10996 usrc1 &= mask;
10997 int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
10998
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010999 bool cond = false;
Martyn Capewellf0844012020-10-23 16:38:26 +010011000 switch (form_hash_) {
11001 case Hash("whilele_p_p_rr"):
11002 cond = ssrc1 <= ssrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070011003 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011004 case Hash("whilelo_p_p_rr"):
11005 cond = usrc1 < usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011006 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011007 case Hash("whilels_p_p_rr"):
11008 cond = usrc1 <= usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011009 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010011010 case Hash("whilelt_p_p_rr"):
11011 cond = ssrc1 < ssrc2;
11012 break;
11013 case Hash("whilege_p_p_rr"):
11014 cond = ssrc1 >= ssrc2;
11015 break;
11016 case Hash("whilegt_p_p_rr"):
11017 cond = ssrc1 > ssrc2;
11018 break;
11019 case Hash("whilehi_p_p_rr"):
11020 cond = usrc1 > usrc2;
11021 break;
11022 case Hash("whilehs_p_p_rr"):
11023 cond = usrc1 >= usrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070011024 break;
11025 default:
TatWai Chongc844bb22019-06-10 15:32:53 -070011026 VIXL_UNIMPLEMENTED();
11027 break;
11028 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011029 last = last && cond;
11030 LogicPRegister dst(pd);
Martyn Capewellf0844012020-10-23 16:38:26 +010011031 int lane = reverse ? ((lane_count - 1) - i) : i;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011032 dst.SetActive(vform, lane, last);
Martyn Capewellf0844012020-10-23 16:38:26 +010011033 usrc1 += reverse ? -1 : 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011034 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011035
11036 PredTest(vform, GetPTrue(), pd);
11037 LogSystemRegister(NZCV);
11038}
11039
11040void Simulator::VisitSVEConditionallyTerminateScalars(
11041 const Instruction* instr) {
11042 unsigned rn_code = instr->GetRn();
11043 unsigned rm_code = instr->GetRm();
11044 bool is_64_bit = instr->ExtractBit(22) == 1;
11045 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
11046 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11047 bool term;
11048 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
11049 case CTERMEQ_rr:
11050 term = src1 == src2;
11051 break;
11052 case CTERMNE_rr:
11053 term = src1 != src2;
11054 break;
11055 default:
11056 term = false;
11057 VIXL_UNIMPLEMENTED();
11058 break;
11059 }
11060 ReadNzcv().SetN(term ? 1 : 0);
11061 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -070011062 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011063}
11064
11065void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011066 bool commute_inputs = false;
11067 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011068 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11069 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011070 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011071 break;
11072 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011073 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011074 break;
11075 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011076 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011077 break;
11078 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011079 cond = ge;
11080 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011081 break;
11082 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011083 cond = gt;
11084 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011085 break;
11086 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011087 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011088 break;
11089 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011090 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011091 VIXL_UNIMPLEMENTED();
11092 break;
11093 }
TatWai Chong302729c2019-06-14 16:18:51 -070011094
11095 VectorFormat vform = instr->GetSVEVectorFormat();
11096 SimVRegister src2;
11097 dup_immediate(vform,
11098 src2,
11099 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11100 SVEIntCompareVectorsHelper(cond,
11101 vform,
11102 ReadPRegister(instr->GetPd()),
11103 ReadPRegister(instr->GetPgLow8()),
11104 commute_inputs ? src2
11105 : ReadVRegister(instr->GetRn()),
11106 commute_inputs ? ReadVRegister(instr->GetRn())
11107 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011108}
11109
11110void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011111 bool commute_inputs = false;
11112 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011113 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11114 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011115 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011116 break;
11117 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011118 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011119 break;
11120 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011121 cond = hi;
11122 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011123 break;
11124 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011125 cond = hs;
11126 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011127 break;
11128 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011129 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011130 VIXL_UNIMPLEMENTED();
11131 break;
11132 }
TatWai Chong302729c2019-06-14 16:18:51 -070011133
11134 VectorFormat vform = instr->GetSVEVectorFormat();
11135 SimVRegister src2;
11136 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11137 SVEIntCompareVectorsHelper(cond,
11138 vform,
11139 ReadPRegister(instr->GetPd()),
11140 ReadPRegister(instr->GetPgLow8()),
11141 commute_inputs ? src2
11142 : ReadVRegister(instr->GetRn()),
11143 commute_inputs ? ReadVRegister(instr->GetRn())
11144 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011145}
11146
11147void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -070011148 Instr op = instr->Mask(SVEIntCompareVectorsMask);
11149 bool is_wide_elements = false;
11150 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011151 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -070011152 case CMPGE_p_p_zw:
11153 case CMPGT_p_p_zw:
11154 case CMPHI_p_p_zw:
11155 case CMPHS_p_p_zw:
11156 case CMPLE_p_p_zw:
11157 case CMPLO_p_p_zw:
11158 case CMPLS_p_p_zw:
11159 case CMPLT_p_p_zw:
11160 case CMPNE_p_p_zw:
11161 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011162 break;
TatWai Chong96713fe2019-06-04 16:39:37 -070011163 }
11164
TatWai Chong302729c2019-06-14 16:18:51 -070011165 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -070011166 switch (op) {
11167 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011168 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011169 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011170 break;
11171 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011172 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011173 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011174 break;
11175 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011176 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011177 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011178 break;
11179 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011180 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011181 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011182 break;
11183 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011184 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011185 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011186 break;
11187 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011188 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011189 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -070011190 break;
11191 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011192 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -070011193 break;
11194 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011195 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -070011196 break;
11197 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011198 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -070011199 break;
11200 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011201 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011202 break;
11203 default:
11204 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -070011205 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011206 break;
11207 }
TatWai Chong96713fe2019-06-04 16:39:37 -070011208
TatWai Chong302729c2019-06-14 16:18:51 -070011209 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -070011210 instr->GetSVEVectorFormat(),
11211 ReadPRegister(instr->GetPd()),
11212 ReadPRegister(instr->GetPgLow8()),
11213 ReadVRegister(instr->GetRn()),
11214 ReadVRegister(instr->GetRm()),
11215 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011216}
11217
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011218void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011219 VectorFormat vform = instr->GetSVEVectorFormat();
11220 SimVRegister& zd = ReadVRegister(instr->GetRd());
11221 SimVRegister& zn = ReadVRegister(instr->GetRn());
11222
11223 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11224 (vform == kFormatVnD));
11225
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011226 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011227 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +000011228 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011229 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011230 default:
11231 VIXL_UNIMPLEMENTED();
11232 break;
11233 }
11234}
11235
11236void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011237 VectorFormat vform = instr->GetSVEVectorFormat();
11238 SimVRegister& zd = ReadVRegister(instr->GetRd());
11239 SimVRegister& zn = ReadVRegister(instr->GetRn());
11240 SimVRegister& zm = ReadVRegister(instr->GetRm());
11241
11242 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11243 (vform == kFormatVnD));
11244
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011245 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011246 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +000011247 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011248 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011249 default:
11250 VIXL_UNIMPLEMENTED();
11251 break;
11252 }
11253}
11254
11255void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11256 const Instruction* instr) {
11257 SimVRegister& zd = ReadVRegister(instr->GetRd());
11258 SimVRegister& zn = ReadVRegister(instr->GetRn());
11259
11260 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011261 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011262 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11263 // Record the movprfx, so the next ExecuteInstruction() can check it.
11264 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011265 break;
11266 default:
11267 VIXL_UNIMPLEMENTED();
11268 break;
11269 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011270}
11271
11272void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +010011273 VectorFormat vform = instr->GetSVEVectorFormat();
11274
11275 SimVRegister& zd = ReadVRegister(instr->GetRd());
11276 SimVRegister& zm = ReadVRegister(instr->GetRm());
11277
11278 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011279 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011280 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011281 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011282 break;
11283 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011284 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011285 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011286 case MAD_z_p_zzz:
11287 // 'za' is encoded in 'Rn'.
11288 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011289 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011290 case MSB_z_p_zzz: {
11291 // 'za' is encoded in 'Rn'.
11292 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11293 break;
11294 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011295 default:
11296 VIXL_UNIMPLEMENTED();
11297 break;
11298 }
Jacob Bramley22023df2019-05-14 17:55:43 +010011299 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011300}
11301
11302void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011303 VectorFormat vform = instr->GetSVEVectorFormat();
11304 SimVRegister& zda = ReadVRegister(instr->GetRd());
11305 SimVRegister& zn = ReadVRegister(instr->GetRn());
11306 SimVRegister& zm = ReadVRegister(instr->GetRm());
11307
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011308 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
11309 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011310 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011311 break;
11312 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011313 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011314 break;
11315 default:
11316 VIXL_UNIMPLEMENTED();
11317 break;
11318 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011319}
11320
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011321void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011322 VectorFormat vform = instr->GetSVEVectorFormat();
11323 SimVRegister& zn = ReadVRegister(instr->GetRn());
11324 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11325 SimVRegister& zd = ReadVRegister(instr->GetRd());
11326
11327 switch (instr->Mask(SVEMovprfxMask)) {
11328 case MOVPRFX_z_p_z:
11329 if (instr->ExtractBit(16)) {
11330 mov_merging(vform, zd, pg, zn);
11331 } else {
11332 mov_zeroing(vform, zd, pg, zn);
11333 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011334
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011335 // Record the movprfx, so the next ExecuteInstruction() can check it.
11336 movprfx_ = instr;
11337 break;
11338 default:
11339 VIXL_UNIMPLEMENTED();
11340 break;
11341 }
11342}
11343
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011344void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011345 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +010011346 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011347 SimVRegister& zn = ReadVRegister(instr->GetRn());
11348 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11349
11350 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11351 switch (instr->Mask(SVEIntReductionLogicalMask)) {
11352 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011353 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011354 break;
11355 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011356 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011357 break;
11358 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011359 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011360 break;
11361 default:
11362 VIXL_UNIMPLEMENTED();
11363 break;
11364 }
11365 } else {
11366 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011367 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011368 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011369 break;
11370 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011371 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011372 break;
11373 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011374 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011375 break;
11376 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011377 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011378 break;
11379 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011380 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011381 break;
11382 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011383 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011384 break;
11385 default:
11386 VIXL_UNIMPLEMENTED();
11387 break;
11388 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011389 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011390}
11391
11392void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011393 VectorFormat vform = instr->GetSVEVectorFormat();
11394 SimVRegister& zn = ReadVRegister(instr->GetRn());
11395
11396 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011397 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11398 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011399 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011400 break;
11401 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011402 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011403 break;
11404 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011405 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011406 break;
11407 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011408 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011409 break;
11410 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011411 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011412 break;
11413 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011414 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011415 break;
11416 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011417 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011418 break;
11419 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011420 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011421 break;
11422 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011423 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011424 break;
11425 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011426 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011427 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011428 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011429 break;
11430 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011431 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011432 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011433 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011434 break;
11435 default:
11436 VIXL_UNIMPLEMENTED();
11437 break;
11438 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011439
11440 SimVRegister& zd = ReadVRegister(instr->GetRd());
11441 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11442 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011443}
11444
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011445void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011446 // There is only one instruction in this group.
11447 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11448
11449 VectorFormat vform = instr->GetSVEVectorFormat();
11450 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11451 SimVRegister& zd = ReadVRegister(instr->GetRd());
11452
Martyn Capewell310a0822020-09-08 20:09:17 +010011453 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11454
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011455 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011456 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011457 case FCPY_z_p_i: {
11458 int imm8 = instr->ExtractBits(12, 5);
11459 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11460 Instruction::Imm8ToFP64(imm8));
11461 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011462 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011463 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011464 default:
11465 VIXL_UNIMPLEMENTED();
11466 break;
11467 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011468 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011469}
11470
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011471void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11472 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +010011473 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010011474 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +010011475 SimVRegister scratch;
11476
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011477 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11478 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011479
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011480 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011481 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011482 add_uint(vform, zd, zd, imm);
11483 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011484 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011485 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11486 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011487 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011488 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11489 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011490 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011491 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +010011492 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011493 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011494 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011495 sub_uint(vform, zd, zd, imm);
11496 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011497 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011498 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11499 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011500 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011501 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11502 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011503 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011504 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011505 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011506}
TatWai Chong6995bfd2019-09-26 10:48:05 +010011507
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011508void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11509 SimVRegister& zd = ReadVRegister(instr->GetRd());
11510
Martyn Capewell8ed83522020-08-11 16:19:43 +010011511 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011512 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +010011513 int shift = instr->ExtractBit(13) * 8;
11514 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011515
11516 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11517 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +010011518 // The encoding of byte-sized lanes with lsl #8 is undefined.
11519 if ((format == kFormatVnB) && (shift == 8)) {
11520 VIXL_UNIMPLEMENTED();
11521 } else {
11522 dup_immediate(format, zd, imm);
11523 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011524 break;
11525 default:
11526 VIXL_UNIMPLEMENTED();
11527 break;
11528 }
11529}
11530
11531void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11532 VectorFormat vform = instr->GetSVEVectorFormat();
11533 SimVRegister& zd = ReadVRegister(instr->GetRd());
11534
11535 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011536 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +010011537 switch (vform) {
11538 case kFormatVnH:
11539 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11540 break;
11541 case kFormatVnS:
11542 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11543 break;
11544 case kFormatVnD:
11545 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11546 break;
11547 default:
11548 VIXL_UNIMPLEMENTED();
11549 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011550 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011551 default:
11552 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011553 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011554 }
11555}
11556
11557void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11558 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011559 switch (instr->Mask(
11560 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11561 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011562 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011563 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011564 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011565 break;
11566 default:
11567 VIXL_UNIMPLEMENTED();
11568 break;
11569 }
TatWai Chong113d9192020-05-19 01:02:36 -070011570
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011571 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11572 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011573}
11574
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011575void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011576 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011577 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11578 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011579 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011580 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011581 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011582 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011583 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011584 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011585 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011586 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011587 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011588 break;
11589 default:
11590 VIXL_UNIMPLEMENTED();
11591 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011592 }
TatWai Chong113d9192020-05-19 01:02:36 -070011593
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011594 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11595 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011596}
11597
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011598void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11599 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011600 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11601 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011602 VIXL_UNIMPLEMENTED();
11603 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011604 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011605 VIXL_UNIMPLEMENTED();
11606 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011607 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011608 VIXL_UNIMPLEMENTED();
11609 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011610 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011611 VIXL_UNIMPLEMENTED();
11612 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011613 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011614 VIXL_UNIMPLEMENTED();
11615 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011616 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011617 VIXL_UNIMPLEMENTED();
11618 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011619 case LDFF1H_z_p_ai_s:
11620 VIXL_UNIMPLEMENTED();
11621 break;
11622 case LDFF1SB_z_p_ai_s:
11623 VIXL_UNIMPLEMENTED();
11624 break;
11625 case LDFF1SH_z_p_ai_s:
11626 VIXL_UNIMPLEMENTED();
11627 break;
11628 case LDFF1W_z_p_ai_s:
11629 VIXL_UNIMPLEMENTED();
11630 break;
11631 default:
11632 VIXL_UNIMPLEMENTED();
11633 break;
11634 }
11635}
11636
11637void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11638 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011639 switch (
11640 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11641 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011642 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011643 break;
11644 default:
11645 VIXL_UNIMPLEMENTED();
11646 break;
11647 }
TatWai Chong113d9192020-05-19 01:02:36 -070011648
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011649 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11650 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011651}
11652
11653void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11654 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011655 switch (
11656 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011657 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011658 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011659 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011660 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011661 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011662 break;
11663 default:
11664 VIXL_UNIMPLEMENTED();
11665 break;
11666 }
11667}
11668
11669void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11670 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011671 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011672 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011673 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011674 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011675 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011676 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011677 break;
11678 default:
11679 VIXL_UNIMPLEMENTED();
11680 break;
11681 }
11682}
11683
11684void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11685 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011686 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011687 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011688 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011689 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011690 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011691 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011692 break;
11693 default:
11694 VIXL_UNIMPLEMENTED();
11695 break;
11696 }
11697}
11698
11699void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11700 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011701 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011702 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011703 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011704 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011705 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011706 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +010011707 if (instr->GetRm() == kZeroRegCode) {
11708 VIXL_UNIMPLEMENTED();
11709 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011710 break;
11711 default:
11712 VIXL_UNIMPLEMENTED();
11713 break;
11714 }
11715}
11716
11717void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -070011718 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011719 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011720 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -070011721 case LD1RB_z_p_bi_u16:
11722 case LD1RB_z_p_bi_u32:
11723 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011724 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011725 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011726 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -070011727 case LD1RW_z_p_bi_u32:
11728 case LD1RW_z_p_bi_u64:
11729 case LD1RD_z_p_bi_u64:
11730 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011731 break;
11732 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011733 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011734 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011735 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011736 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011737 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -070011738 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011739 break;
11740 default:
TatWai Chong85e15102020-05-04 21:00:40 -070011741 // This encoding group is complete, so no other values should be possible.
11742 VIXL_UNREACHABLE();
11743 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011744 break;
11745 }
TatWai Chong85e15102020-05-04 21:00:40 -070011746
11747 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11748 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11749 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11750 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11751 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11752 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11753 VectorFormat unpack_vform =
11754 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11755 SimVRegister temp;
11756 ld1r(vform, unpack_vform, temp, base, is_signed);
11757 mov_zeroing(vform,
11758 ReadVRegister(instr->GetRt()),
11759 ReadPRegister(instr->GetPgLow8()),
11760 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011761}
11762
11763void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11764 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11765 case LDR_p_bi: {
11766 SimPRegister& pt = ReadPRegister(instr->GetPt());
11767 int pl = GetPredicateLengthInBytes();
11768 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11769 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11770 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11771 for (int i = 0; i < pl; i++) {
11772 pt.Insert(i, Memory::Read<uint8_t>(address + i));
11773 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011774 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011775 break;
11776 }
11777 default:
11778 VIXL_UNIMPLEMENTED();
11779 break;
11780 }
11781}
11782
11783void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011784 switch (instr->Mask(SVELoadVectorRegisterMask)) {
11785 case LDR_z_bi: {
11786 SimVRegister& zt = ReadVRegister(instr->GetRt());
11787 int vl = GetVectorLengthInBytes();
11788 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11789 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11790 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11791 for (int i = 0; i < vl; i++) {
11792 zt.Insert(i, Memory::Read<uint8_t>(address + i));
11793 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011794 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011795 break;
11796 }
11797 default:
11798 VIXL_UNIMPLEMENTED();
11799 break;
11800 }
11801}
11802
11803void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11804 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011805 switch (instr->Mask(
11806 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011807 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011808 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011809 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011810 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011811 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011812 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011813 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011814 case LDFF1D_z_p_bz_d_x32_scaled:
11815 case LDFF1SH_z_p_bz_d_x32_scaled:
11816 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011817 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011818 default:
11819 VIXL_UNIMPLEMENTED();
11820 break;
11821 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011822
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011823 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11824 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011825}
11826
11827void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11828 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011829 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11830 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011831 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011832 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011833 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011834 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011835 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011836 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011837 case LDFF1D_z_p_bz_d_64_scaled:
11838 case LDFF1SH_z_p_bz_d_64_scaled:
11839 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011840 break;
11841 default:
11842 VIXL_UNIMPLEMENTED();
11843 break;
11844 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011845
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011846 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011847}
11848
11849void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11850 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011851 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11852 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011853 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011854 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011855 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011856 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011857 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011858 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011859 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011860 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011861 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011862 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011863 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011864 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011865 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011866 break;
11867 default:
11868 VIXL_UNIMPLEMENTED();
11869 break;
11870 }
TatWai Chong113d9192020-05-19 01:02:36 -070011871
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011872 SVEGatherLoadScalarPlusVectorHelper(instr,
11873 kFormatVnD,
11874 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011875}
11876
11877void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11878 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011879 switch (instr->Mask(
11880 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11881 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011882 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011883 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011884 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011885 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011886 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011887 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011888 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011889 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011890 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011891 case LDFF1D_z_p_bz_d_x32_unscaled:
11892 case LDFF1SB_z_p_bz_d_x32_unscaled:
11893 case LDFF1SH_z_p_bz_d_x32_unscaled:
11894 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011895 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011896 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011897 VIXL_UNIMPLEMENTED();
11898 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011899 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011900
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011901 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11902 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011903}
11904
11905void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11906 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011907 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11908 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011909 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011910 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011911 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011912 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011913 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011914 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011915 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011916 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011917 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011918 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011919 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011920 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011921 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011922 break;
11923 default:
11924 VIXL_UNIMPLEMENTED();
11925 break;
11926 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +000011927 bool is_signed = instr->ExtractBit(14) == 0;
11928 bool is_ff = instr->ExtractBit(13) == 1;
11929 // Note that these instructions don't use the Dtype encoding.
11930 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11931 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11932 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11933 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11934 if (is_ff) {
11935 VIXL_UNIMPLEMENTED();
11936 } else {
11937 SVEStructuredLoadHelper(kFormatVnD,
11938 ReadPRegister(instr->GetPgLow8()),
11939 instr->GetRt(),
11940 addr,
11941 is_signed);
11942 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011943}
11944
11945void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11946 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011947 switch (
11948 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011949 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011950 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011951 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011952 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011953 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011954 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011955 default:
11956 VIXL_UNIMPLEMENTED();
11957 break;
11958 }
11959}
11960
11961void Simulator::
11962 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
11963 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011964 switch (instr->Mask(
11965 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011966 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011967 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011968 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011969 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011970 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011971 break;
11972 default:
11973 VIXL_UNIMPLEMENTED();
11974 break;
11975 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011976}
11977
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011978void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
11979 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011980 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011981 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011982 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011983 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011984 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011985 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011986 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011987 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011988 VIXL_UNIMPLEMENTED();
11989 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011990 }
11991}
11992
11993void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
11994 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +000011995 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +000011996 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011997 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011998 case LDFF1B_z_p_br_u16:
11999 case LDFF1B_z_p_br_u32:
12000 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012001 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012002 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012003 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012004 case LDFF1W_z_p_br_u32:
12005 case LDFF1W_z_p_br_u64:
12006 case LDFF1D_z_p_br_u64:
12007 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012008 break;
12009 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012010 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012011 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012012 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012013 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012014 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012015 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012016 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012017 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012018 // This encoding group is complete, so no other values should be possible.
12019 VIXL_UNREACHABLE();
12020 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012021 break;
12022 }
Jacob Bramley85a9c102019-12-09 17:48:29 +000012023
12024 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12025 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12026 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12027 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12028 uint64_t offset = ReadXRegister(instr->GetRm());
12029 offset <<= msize_in_bytes_log2;
12030 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12031 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12032 SVEFaultTolerantLoadHelper(vform,
12033 ReadPRegister(instr->GetPgLow8()),
12034 instr->GetRt(),
12035 addr,
12036 kSVEFirstFaultLoad,
12037 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012038}
12039
12040void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
12041 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012042 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012043 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012044 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012045 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012046 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012047 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012048 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012049 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012050 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012051 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012052 case LDNF1W_z_p_bi_u32:
12053 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012054 break;
12055 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012056 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012057 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012058 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012059 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012060 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012061 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012062 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012063 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012064 VIXL_UNIMPLEMENTED();
12065 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012066 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012067 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12068 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12069 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12070 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12071 int vl = GetVectorLengthInBytes();
12072 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12073 uint64_t offset =
12074 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12075 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12076 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12077 SVEFaultTolerantLoadHelper(vform,
12078 ReadPRegister(instr->GetPgLow8()),
12079 instr->GetRt(),
12080 addr,
12081 kSVENonFaultLoad,
12082 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012083}
12084
12085void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12086 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012087 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12088 VectorFormat vform = kFormatUndefined;
12089
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012090 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12091 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012092 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012093 break;
12094 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012095 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012096 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012097 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012098 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012099 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012100 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012101 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012102 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012103 default:
12104 VIXL_UNIMPLEMENTED();
12105 break;
12106 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012107 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12108 int vl = GetVectorLengthInBytes();
12109 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12110 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12111 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12112 SVEStructuredLoadHelper(vform,
12113 pg,
12114 instr->GetRt(),
12115 addr,
12116 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012117}
12118
12119void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12120 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012121 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12122 VectorFormat vform = kFormatUndefined;
12123
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012124 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12125 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012126 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012127 break;
12128 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012129 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012130 break;
12131 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012132 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012133 break;
12134 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012135 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012136 break;
12137 default:
12138 VIXL_UNIMPLEMENTED();
12139 break;
12140 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012141 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12142 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12143 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12144 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12145 SVEStructuredLoadHelper(vform,
12146 pg,
12147 instr->GetRt(),
12148 addr,
12149 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012150}
12151
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012152void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
12153 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012154 SimVRegister& zt = ReadVRegister(instr->GetRt());
12155 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12156
12157 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12158 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
12159
12160 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012161 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
12162 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012163 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012164 break;
12165 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012166 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012167 break;
12168 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012169 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012170 break;
12171 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012172 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012173 break;
12174 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012175 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012176 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012177 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012178 ld1(kFormat16B, zt, addr + offset);
12179 mov_zeroing(vform, zt, pg, zt);
12180 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012181}
12182
12183void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
12184 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012185 SimVRegister& zt = ReadVRegister(instr->GetRt());
12186 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12187
12188 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12189 uint64_t offset = ReadXRegister(instr->GetRm());
12190
12191 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012192 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
12193 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012194 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012195 break;
12196 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012197 vform = kFormatVnD;
12198 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012199 break;
12200 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012201 vform = kFormatVnH;
12202 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012203 break;
12204 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012205 vform = kFormatVnS;
12206 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012207 break;
12208 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012209 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012210 break;
12211 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012212 ld1(kFormat16B, zt, addr + offset);
12213 mov_zeroing(vform, zt, pg, zt);
12214 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012215}
12216
12217void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12218 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012219 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12220 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012221 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012222 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012223 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012224 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012225 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012226 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012227 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012228 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012229 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012230 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012231 case LD4W_z_p_bi_contiguous: {
12232 int vl = GetVectorLengthInBytes();
12233 int msz = instr->ExtractBits(24, 23);
12234 int reg_count = instr->ExtractBits(22, 21) + 1;
12235 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12236 LogicSVEAddressVector addr(
12237 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12238 addr.SetMsizeInBytesLog2(msz);
12239 addr.SetRegCount(reg_count);
12240 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12241 ReadPRegister(instr->GetPgLow8()),
12242 instr->GetRt(),
12243 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012244 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012245 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012246 default:
12247 VIXL_UNIMPLEMENTED();
12248 break;
12249 }
12250}
12251
12252void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12253 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012254 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12255 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012256 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012257 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012258 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012259 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012260 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012261 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012262 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012263 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012264 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012265 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000012266 case LD4W_z_p_br_contiguous: {
12267 int msz = instr->ExtractBits(24, 23);
12268 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12269 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12270 LogicSVEAddressVector addr(
12271 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12272 addr.SetMsizeInBytesLog2(msz);
12273 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12274 SVEStructuredLoadHelper(vform,
12275 ReadPRegister(instr->GetPgLow8()),
12276 instr->GetRt(),
12277 addr,
12278 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012279 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000012280 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012281 default:
12282 VIXL_UNIMPLEMENTED();
12283 break;
12284 }
12285}
12286
12287void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12288 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012289 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12290 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012291 case ST1W_z_p_bz_s_x32_scaled: {
12292 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12293 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12294 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12295 uint64_t base = ReadXRegister(instr->GetRn());
12296 SVEOffsetModifier mod =
12297 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12298 LogicSVEAddressVector addr(base,
12299 &ReadVRegister(instr->GetRm()),
12300 kFormatVnS,
12301 mod,
12302 scale);
12303 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12304 SVEStructuredStoreHelper(kFormatVnS,
12305 ReadPRegister(instr->GetPgLow8()),
12306 instr->GetRt(),
12307 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012308 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012309 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012310 default:
12311 VIXL_UNIMPLEMENTED();
12312 break;
12313 }
12314}
12315
12316void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12317 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012318 switch (
12319 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12320 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012321 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012322 case ST1W_z_p_bz_s_x32_unscaled: {
12323 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12324 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12325 uint64_t base = ReadXRegister(instr->GetRn());
12326 SVEOffsetModifier mod =
12327 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12328 LogicSVEAddressVector addr(base,
12329 &ReadVRegister(instr->GetRm()),
12330 kFormatVnS,
12331 mod);
12332 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12333 SVEStructuredStoreHelper(kFormatVnS,
12334 ReadPRegister(instr->GetPgLow8()),
12335 instr->GetRt(),
12336 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012337 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012338 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012339 default:
12340 VIXL_UNIMPLEMENTED();
12341 break;
12342 }
12343}
12344
12345void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12346 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012347 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012348 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12349 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012350 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012351 break;
12352 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012353 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012354 break;
12355 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012356 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012357 break;
12358 default:
12359 VIXL_UNIMPLEMENTED();
12360 break;
12361 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012362 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12363 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12364 addr.SetMsizeInBytesLog2(msz);
12365 SVEStructuredStoreHelper(kFormatVnS,
12366 ReadPRegister(instr->GetPgLow8()),
12367 instr->GetRt(),
12368 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012369}
12370
12371void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12372 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012373 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12374 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012375 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012376 case ST1W_z_p_bz_d_64_scaled: {
12377 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12378 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12379 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12380 uint64_t base = ReadXRegister(instr->GetRn());
12381 LogicSVEAddressVector addr(base,
12382 &ReadVRegister(instr->GetRm()),
12383 kFormatVnD,
12384 SVE_LSL,
12385 scale);
12386 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12387 SVEStructuredStoreHelper(kFormatVnD,
12388 ReadPRegister(instr->GetPgLow8()),
12389 instr->GetRt(),
12390 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012391 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012392 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012393 default:
12394 VIXL_UNIMPLEMENTED();
12395 break;
12396 }
12397}
12398
12399void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12400 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012401 switch (
12402 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12403 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012404 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012405 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012406 case ST1W_z_p_bz_d_64_unscaled: {
12407 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12408 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012409 uint64_t base = ReadXRegister(instr->GetRn());
12410 LogicSVEAddressVector addr(base,
12411 &ReadVRegister(instr->GetRm()),
12412 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070012413 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012414 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12415 SVEStructuredStoreHelper(kFormatVnD,
12416 ReadPRegister(instr->GetPgLow8()),
12417 instr->GetRt(),
12418 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012419 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012420 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012421 default:
12422 VIXL_UNIMPLEMENTED();
12423 break;
12424 }
12425}
12426
12427void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12428 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012429 switch (instr->Mask(
12430 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12431 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012432 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012433 case ST1W_z_p_bz_d_x32_scaled: {
12434 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12435 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12436 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12437 uint64_t base = ReadXRegister(instr->GetRn());
12438 SVEOffsetModifier mod =
12439 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12440 LogicSVEAddressVector addr(base,
12441 &ReadVRegister(instr->GetRm()),
12442 kFormatVnD,
12443 mod,
12444 scale);
12445 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12446 SVEStructuredStoreHelper(kFormatVnD,
12447 ReadPRegister(instr->GetPgLow8()),
12448 instr->GetRt(),
12449 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012450 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012451 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012452 default:
12453 VIXL_UNIMPLEMENTED();
12454 break;
12455 }
12456}
12457
12458void Simulator::
12459 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12460 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012461 switch (instr->Mask(
12462 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12463 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012464 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012465 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012466 case ST1W_z_p_bz_d_x32_unscaled: {
12467 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12468 VIXL_ASSERT(kDRegSizeInBytesLog2 >= 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 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12477 SVEStructuredStoreHelper(kFormatVnD,
12478 ReadPRegister(instr->GetPgLow8()),
12479 instr->GetRt(),
12480 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012481 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012482 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012483 default:
12484 VIXL_UNIMPLEMENTED();
12485 break;
12486 }
12487}
12488
12489void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12490 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012491 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012492 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12493 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012494 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012495 break;
12496 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012497 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012498 break;
12499 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012500 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012501 break;
12502 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012503 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012504 break;
12505 default:
12506 VIXL_UNIMPLEMENTED();
12507 break;
12508 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012509 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12510 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12511 addr.SetMsizeInBytesLog2(msz);
12512 SVEStructuredStoreHelper(kFormatVnD,
12513 ReadPRegister(instr->GetPgLow8()),
12514 instr->GetRt(),
12515 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012516}
12517
12518void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12519 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012520 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12521 VectorFormat vform = kFormatUndefined;
12522
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012523 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12524 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012525 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012526 break;
12527 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012528 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012529 break;
12530 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012531 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012532 break;
12533 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012534 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012535 break;
12536 default:
12537 VIXL_UNIMPLEMENTED();
12538 break;
12539 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012540 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12541 int vl = GetVectorLengthInBytes();
12542 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12543 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12544 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12545 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012546}
12547
12548void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12549 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012550 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12551 VectorFormat vform = kFormatUndefined;
12552
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012553 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12554 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012555 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012556 break;
12557 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012558 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012559 break;
12560 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012561 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012562 break;
12563 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012564 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012565 break;
12566 default:
12567 VIXL_UNIMPLEMENTED();
12568 break;
12569 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012570 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12571 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12572 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12573 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12574 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012575}
12576
12577void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12578 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012579 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12580 case ST1B_z_p_bi:
12581 case ST1D_z_p_bi:
12582 case ST1H_z_p_bi:
12583 case ST1W_z_p_bi: {
12584 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012585 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12586 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12587 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12588 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12589 uint64_t offset =
12590 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012591 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012592 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012593 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012594 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12595 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012596 ReadPRegister(instr->GetPgLow8()),
12597 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012598 addr);
12599 break;
12600 }
12601 default:
12602 VIXL_UNIMPLEMENTED();
12603 break;
12604 }
12605}
12606
12607void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12608 const Instruction* instr) {
12609 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12610 case ST1B_z_p_br:
12611 case ST1D_z_p_br:
12612 case ST1H_z_p_br:
12613 case ST1W_z_p_br: {
12614 uint64_t offset = ReadXRegister(instr->GetRm());
12615 offset <<= instr->ExtractBits(24, 23);
12616 VectorFormat vform =
12617 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12618 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012619 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12620 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012621 ReadPRegister(instr->GetPgLow8()),
12622 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012623 addr);
12624 break;
12625 }
12626 default:
12627 VIXL_UNIMPLEMENTED();
12628 break;
12629 }
12630}
12631
12632void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12633 const Instruction* instr) {
12634 VectorFormat vform = instr->GetSVEVectorFormat();
12635 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12636 SimVRegister z_result;
12637
12638 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12639 case CPY_z_p_v:
12640 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12641 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12642 break;
12643 default:
12644 VIXL_UNIMPLEMENTED();
12645 break;
12646 }
12647}
12648
12649void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12650 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012651 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12652 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012653 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012654 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012655 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012656 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012657 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012658 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012659 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012660 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012661 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012662 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012663 case ST4W_z_p_bi_contiguous: {
12664 int vl = GetVectorLengthInBytes();
12665 int msz = instr->ExtractBits(24, 23);
12666 int reg_count = instr->ExtractBits(22, 21) + 1;
12667 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12668 LogicSVEAddressVector addr(
12669 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12670 addr.SetMsizeInBytesLog2(msz);
12671 addr.SetRegCount(reg_count);
12672 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12673 ReadPRegister(instr->GetPgLow8()),
12674 instr->GetRt(),
12675 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012676 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012677 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012678 default:
12679 VIXL_UNIMPLEMENTED();
12680 break;
12681 }
12682}
12683
12684void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12685 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012686 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12687 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012688 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012689 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012690 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012691 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012692 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012693 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012694 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012695 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012696 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012697 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012698 case ST4W_z_p_br_contiguous: {
12699 int msz = instr->ExtractBits(24, 23);
12700 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12701 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12702 LogicSVEAddressVector addr(
12703 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12704 addr.SetMsizeInBytesLog2(msz);
12705 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12706 SVEStructuredStoreHelper(vform,
12707 ReadPRegister(instr->GetPgLow8()),
12708 instr->GetRt(),
12709 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012710 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012711 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012712 default:
12713 VIXL_UNIMPLEMENTED();
12714 break;
12715 }
12716}
12717
12718void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12719 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12720 case STR_p_bi: {
12721 SimPRegister& pt = ReadPRegister(instr->GetPt());
12722 int pl = GetPredicateLengthInBytes();
12723 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12724 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12725 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12726 for (int i = 0; i < pl; i++) {
12727 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
12728 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012729 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012730 break;
12731 }
12732 default:
12733 VIXL_UNIMPLEMENTED();
12734 break;
12735 }
12736}
12737
12738void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12739 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12740 case STR_z_bi: {
12741 SimVRegister& zt = ReadVRegister(instr->GetRt());
12742 int vl = GetVectorLengthInBytes();
12743 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12744 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12745 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12746 for (int i = 0; i < vl; i++) {
12747 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
12748 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012749 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012750 break;
12751 }
12752 default:
12753 VIXL_UNIMPLEMENTED();
12754 break;
12755 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012756}
12757
12758void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012759 VectorFormat vform = instr->GetSVEVectorFormat();
12760 SimVRegister& zda = ReadVRegister(instr->GetRd());
12761 SimVRegister& zn = ReadVRegister(instr->GetRn());
12762
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012763 switch (instr->Mask(SVEMulIndexMask)) {
12764 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012765 sdot(vform,
12766 zda,
12767 zn,
12768 ReadVRegister(instr->ExtractBits(19, 16)),
12769 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012770 break;
12771 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012772 sdot(vform,
12773 zda,
12774 zn,
12775 ReadVRegister(instr->ExtractBits(18, 16)),
12776 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012777 break;
12778 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012779 udot(vform,
12780 zda,
12781 zn,
12782 ReadVRegister(instr->ExtractBits(19, 16)),
12783 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012784 break;
12785 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012786 udot(vform,
12787 zda,
12788 zn,
12789 ReadVRegister(instr->ExtractBits(18, 16)),
12790 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012791 break;
12792 default:
12793 VIXL_UNIMPLEMENTED();
12794 break;
12795 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012796}
12797
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012798void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012799 SimPRegister& pd = ReadPRegister(instr->GetPd());
12800 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12801 SimPRegister& pn = ReadPRegister(instr->GetPn());
12802 SimPRegister result;
12803
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012804 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012805 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012806 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012807 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012808 break;
12809 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012810 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012811 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012812 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012813 default:
12814 VIXL_UNIMPLEMENTED();
12815 break;
12816 }
TatWai Chong5d872292020-01-02 15:39:51 -080012817
12818 if (instr->ExtractBit(4) == 1) {
12819 mov_merging(pd, pg, result);
12820 } else {
12821 mov_zeroing(pd, pg, result);
12822 }
12823
12824 // Set flag if needed.
12825 if (instr->ExtractBit(22) == 1) {
12826 PredTest(kFormatVnB, pg, pd);
12827 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012828}
12829
12830void Simulator::VisitSVEPropagateBreakToNextPartition(
12831 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012832 SimPRegister& pdm = ReadPRegister(instr->GetPd());
12833 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12834 SimPRegister& pn = ReadPRegister(instr->GetPn());
12835
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012836 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012837 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012838 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080012839 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012840 break;
12841 default:
12842 VIXL_UNIMPLEMENTED();
12843 break;
12844 }
TatWai Chong5d872292020-01-02 15:39:51 -080012845
12846 // Set flag if needed.
12847 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010012848 // Note that this ignores `pg`.
12849 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080012850 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012851}
12852
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012853void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012854 SimPRegister& pd = ReadPRegister(instr->GetPd());
12855 SimPRegister& pn = ReadPRegister(instr->GetPn());
12856
12857 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12858 SimVRegister zero;
12859 dup_immediate(kFormatVnB, zero, 0);
12860
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012861 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012862 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012863 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012864 break;
12865 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012866 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012867 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012868 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012869 VIXL_UNIMPLEMENTED();
12870 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012871 }
TatWai Chong47c26842020-02-10 01:51:32 -080012872 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012873}
12874
12875void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012876 VectorFormat vform = instr->GetSVEVectorFormat();
12877 SimPRegister& pd = ReadPRegister(instr->GetPd());
12878 SimPRegister& pn = ReadPRegister(instr->GetPn());
12879 SimPRegister& pm = ReadPRegister(instr->GetPm());
12880
12881 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12882 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12883
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012884 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012885 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012886 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012887 break;
12888 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012889 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012890 break;
12891 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012892 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012893 break;
12894 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012895 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012896 break;
12897 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012898 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012899 break;
12900 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012901 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012902 break;
12903 default:
12904 VIXL_UNIMPLEMENTED();
12905 break;
12906 }
TatWai Chong47c26842020-02-10 01:51:32 -080012907 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012908}
12909
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012910void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012911 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012912 case REV_p_p: {
12913 VectorFormat vform = instr->GetSVEVectorFormat();
12914 SimPRegister& pn = ReadPRegister(instr->GetPn());
12915 SimPRegister& pd = ReadPRegister(instr->GetPd());
12916 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12917 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080012918 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012919 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012920 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012921 default:
12922 VIXL_UNIMPLEMENTED();
12923 break;
12924 }
12925}
12926
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012927void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000012928 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12929 // Second source register "Zm" is encoded where "Zn" would usually be.
12930 SimVRegister& zm = ReadVRegister(instr->GetRn());
12931
12932 const int imm8h_mask = 0x001F0000;
12933 const int imm8l_mask = 0x00001C00;
12934 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
12935 int vl = GetVectorLengthInBytes();
12936 index = (index >= vl) ? 0 : index;
12937
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012938 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
12939 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000012940 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012941 break;
12942 default:
12943 VIXL_UNIMPLEMENTED();
12944 break;
12945 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012946}
12947
12948void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000012949 VectorFormat vform = instr->GetSVEVectorFormat();
12950 SimVRegister& zd = ReadVRegister(instr->GetRd());
12951 SimVRegister& zn = ReadVRegister(instr->GetRn());
12952 SimVRegister& zm = ReadVRegister(instr->GetRm());
12953
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012954 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
12955 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012956 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012957 break;
12958 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012959 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012960 break;
12961 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012962 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012963 break;
12964 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012965 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012966 break;
12967 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012968 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012969 break;
12970 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012971 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012972 break;
12973 default:
12974 VIXL_UNIMPLEMENTED();
12975 break;
12976 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012977}
12978
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012979void Simulator::VisitSVEConditionallyBroadcastElementToVector(
12980 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012981 VectorFormat vform = instr->GetSVEVectorFormat();
12982 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12983 SimVRegister& zm = ReadVRegister(instr->GetRn());
12984 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12985
12986 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012987 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012988 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012989 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012990 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012991 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012992 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012993 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012994 default:
12995 VIXL_UNIMPLEMENTED();
12996 break;
12997 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012998
12999 if (active_offset >= 0) {
13000 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13001 if (value.first) {
13002 dup_immediate(vform, zdn, value.second);
13003 } else {
13004 // Trigger a line of trace for the operation, even though it doesn't
13005 // change the register value.
13006 mov(vform, zdn, zdn);
13007 }
13008 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013009}
13010
13011void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
13012 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013013 VectorFormat vform = instr->GetSVEVectorFormat();
13014 SimVRegister& vdn = 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(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
13020 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013021 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013022 break;
13023 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013024 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013025 break;
13026 default:
13027 VIXL_UNIMPLEMENTED();
13028 break;
13029 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013030
13031 if (active_offset >= 0) {
13032 LogicVRegister dst(vdn);
13033 uint64_t src1_value = dst.Uint(vform, 0);
13034 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
13035 dup_immediate(vform, vdn, 0);
13036 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
13037 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013038}
13039
13040void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
13041 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013042 VectorFormat vform = instr->GetSVEVectorFormat();
13043 SimVRegister& zm = ReadVRegister(instr->GetRn());
13044 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13045
13046 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013047 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
13048 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013049 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013050 break;
13051 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013052 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013053 break;
13054 default:
13055 VIXL_UNIMPLEMENTED();
13056 break;
13057 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013058
13059 if (active_offset >= 0) {
13060 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13061 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13062 GetUintMask(LaneSizeInBitsFromFormat(vform));
13063 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13064 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013065}
13066
13067void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13068 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013069 VectorFormat vform = instr->GetSVEVectorFormat();
13070 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13071 SimVRegister& zm = ReadVRegister(instr->GetRn());
13072 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13073
13074 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013075 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13076 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013077 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013078 break;
13079 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013080 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013081 break;
13082 default:
13083 VIXL_UNIMPLEMENTED();
13084 break;
13085 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013086
13087 if (active_offset >= 0) {
13088 LogicVRegister dst(vdn);
13089 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13090 dup_immediate(vform, vdn, 0);
13091 dst.SetUint(vform, 0, value.second);
13092 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013093}
13094
13095void Simulator::VisitSVEExtractElementToGeneralRegister(
13096 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013097 VectorFormat vform = instr->GetSVEVectorFormat();
13098 SimVRegister& zm = ReadVRegister(instr->GetRn());
13099 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13100
13101 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013102 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13103 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013104 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013105 break;
13106 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013107 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013108 break;
13109 default:
13110 VIXL_UNIMPLEMENTED();
13111 break;
13112 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013113
13114 if (active_offset >= 0) {
13115 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13116 WriteXRegister(instr->GetRd(), value.second);
13117 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013118}
13119
13120void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013121 VectorFormat vform = instr->GetSVEVectorFormat();
13122 SimVRegister& zd = ReadVRegister(instr->GetRd());
13123 SimVRegister& zn = ReadVRegister(instr->GetRn());
13124 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13125
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013126 switch (instr->Mask(SVECompressActiveElementsMask)) {
13127 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013128 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013129 break;
13130 default:
13131 VIXL_UNIMPLEMENTED();
13132 break;
13133 }
13134}
13135
13136void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13137 const Instruction* instr) {
13138 VectorFormat vform = instr->GetSVEVectorFormat();
13139 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13140 SimVRegister z_result;
13141
13142 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013143 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010013144 dup_immediate(vform,
13145 z_result,
13146 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13147 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013148 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013149 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013150 VIXL_UNIMPLEMENTED();
13151 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013152 }
13153}
13154
13155void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013156 VectorFormat vform = instr->GetSVEVectorFormat();
13157 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13158 SimVRegister& zd = ReadVRegister(instr->GetRd());
13159
13160 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013161 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013162 case CPY_z_p_i: {
13163 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
13164 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13165 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013166 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013167 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013168 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013169 VIXL_UNIMPLEMENTED();
13170 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013171 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013172
13173 if (instr->ExtractBit(14) != 0) {
13174 mov_merging(vform, zd, pg, result);
13175 } else {
13176 mov_zeroing(vform, zd, pg, result);
13177 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013178}
13179
13180void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000013181 SimVRegister& zd = ReadVRegister(instr->GetRd());
13182 SimVRegister& zn = ReadVRegister(instr->GetRn());
13183 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13184 SimVRegister result;
13185
13186 // In NEON, the chunk size in which elements are REVersed is in the
13187 // instruction mnemonic, and the element size attached to the register.
13188 // SVE reverses the semantics; the mapping to logic functions below is to
13189 // account for this.
13190 VectorFormat chunk_form = instr->GetSVEVectorFormat();
13191 VectorFormat element_form = kFormatUndefined;
13192
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013193 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013194 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013195 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013196 break;
13197 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013198 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13199 (chunk_form == kFormatVnD));
13200 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013201 break;
13202 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013203 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13204 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013205 break;
13206 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013207 VIXL_ASSERT(chunk_form == kFormatVnD);
13208 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013209 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013210 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013211 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013212 break;
13213 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000013214
13215 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13216 VIXL_ASSERT(element_form != kFormatUndefined);
13217 switch (chunk_form) {
13218 case kFormatVnH:
13219 rev16(element_form, result, zn);
13220 break;
13221 case kFormatVnS:
13222 rev32(element_form, result, zn);
13223 break;
13224 case kFormatVnD:
13225 rev64(element_form, result, zn);
13226 break;
13227 default:
13228 VIXL_UNIMPLEMENTED();
13229 }
13230 }
13231
13232 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013233}
13234
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013235void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013236 VectorFormat vform = instr->GetSVEVectorFormat();
13237 SimVRegister& zdn = ReadVRegister(instr->GetRd());
13238 SimVRegister& zm = ReadVRegister(instr->GetRn());
13239 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13240
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013241 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
13242 case SPLICE_z_p_zz_des:
Martyn Capewellf804b602020-02-24 18:57:18 +000013243 splice(vform, zdn, pg, zdn, zm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013244 break;
13245 default:
13246 VIXL_UNIMPLEMENTED();
13247 break;
13248 }
13249}
TatWai Chong4f28df72019-08-14 17:50:30 -070013250
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013251void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13252 SimVRegister& zd = ReadVRegister(instr->GetRd());
13253 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13254 case DUP_z_r:
13255 dup_immediate(instr->GetSVEVectorFormat(),
13256 zd,
13257 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13258 break;
13259 default:
13260 VIXL_UNIMPLEMENTED();
13261 break;
13262 }
13263}
13264
13265void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13266 SimVRegister& zd = ReadVRegister(instr->GetRd());
13267 VectorFormat vform = instr->GetSVEVectorFormat();
13268 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13269 case INSR_z_v:
13270 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13271 break;
13272 default:
13273 VIXL_UNIMPLEMENTED();
13274 break;
13275 }
13276}
13277
13278void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13279 SimVRegister& zd = ReadVRegister(instr->GetRd());
13280 VectorFormat vform = instr->GetSVEVectorFormat();
13281 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13282 case INSR_z_r:
13283 insr(vform, zd, ReadXRegister(instr->GetRn()));
13284 break;
13285 default:
13286 VIXL_UNIMPLEMENTED();
13287 break;
13288 }
13289}
13290
13291void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13292 SimVRegister& zd = ReadVRegister(instr->GetRd());
13293 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070013294 case DUP_z_zi: {
13295 std::pair<int, int> index_and_lane_size =
13296 instr->GetSVEPermuteIndexAndLaneSizeLog2();
13297 int index = index_and_lane_size.first;
13298 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13299 VectorFormat vform =
13300 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13301 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13302 // Out of bounds, set the destination register to zero.
13303 dup_immediate(kFormatVnD, zd, 0);
13304 } else {
13305 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13306 }
13307 return;
13308 }
TatWai Chong4f28df72019-08-14 17:50:30 -070013309 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013310 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070013311 break;
13312 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013313}
TatWai Chong4f28df72019-08-14 17:50:30 -070013314
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013315void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13316 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070013317 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013318 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013319 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013320 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013321 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013322 default:
13323 VIXL_UNIMPLEMENTED();
13324 break;
13325 }
13326}
13327
13328void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13329 SimVRegister& zd = ReadVRegister(instr->GetRd());
13330 VectorFormat vform = instr->GetSVEVectorFormat();
13331 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013332 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013333 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013334 break;
13335 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013336 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013337 break;
13338 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013339 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013340 break;
13341 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013342 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13343 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013344 default:
13345 VIXL_UNIMPLEMENTED();
13346 break;
13347 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013348}
13349
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013350void Simulator::VisitSVETableLookup(const Instruction* instr) {
Martyn Capewell99c60492020-10-30 08:14:39 +000013351 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013352 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell99c60492020-10-30 08:14:39 +000013353 SimVRegister& zn = ReadVRegister(instr->GetRn());
13354 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13355 SimVRegister& zm = ReadVRegister(instr->GetRm());
13356
13357 switch (form_hash_) {
13358 case Hash("tbl_z_zz_1"):
13359 tbl(vform, zd, zn, zm);
13360 break;
13361 case Hash("tbl_z_zz_2"):
13362 tbl(vform, zd, zn, zn2, zm);
13363 break;
13364 case Hash("tbx_z_zz"):
13365 tbx(vform, zd, zn, zm);
13366 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013367 default:
Martyn Capewell99c60492020-10-30 08:14:39 +000013368 VIXL_UNIMPLEMENTED();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013369 break;
13370 }
13371}
13372
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013373void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013374 VectorFormat vform = instr->GetSVEVectorFormat();
13375 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13376 SimPRegister& pn = ReadPRegister(instr->GetPn());
13377
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013378 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013379 case CNTP_r_p_p: {
13380 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013381 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013382 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013383 default:
13384 VIXL_UNIMPLEMENTED();
13385 break;
13386 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013387}
13388
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013389void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13390 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080013391 SimPRegister& pd = ReadPRegister(instr->GetPd());
13392 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13393 SimPRegister& pn = ReadPRegister(instr->GetPn());
13394 SimPRegister& pm = ReadPRegister(instr->GetPm());
13395 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070013396 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013397 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013398 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013399 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013400 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013401 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013402 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013403 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013404 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013405 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013406 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013407 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013408 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013409 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013410 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070013411 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080013412 result,
13413 pn,
13414 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013415 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080013416 case SEL_p_p_pp:
13417 sel(pd, pg, pn, pm);
13418 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013419 default:
13420 VIXL_UNIMPLEMENTED();
13421 break;
13422 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013423
13424 mov_zeroing(pd, pg, result);
13425 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13426 PredTest(kFormatVnB, pg, pd);
13427 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013428}
13429
Jacob Bramley0ce75842019-07-17 18:12:50 +010013430void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013431 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13432 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13433 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013434 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010013435 pfirst(pdn, pg, pdn);
13436 // TODO: Is this broken when pg == pdn?
13437 PredTest(kFormatVnB, pg, pdn);
13438 break;
13439 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013440 VIXL_UNIMPLEMENTED();
13441 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013442 }
13443}
13444
13445void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013446 // This group only contains PTRUE{S}, and there are no unallocated encodings.
13447 VIXL_STATIC_ASSERT(
13448 SVEPredicateInitializeMask ==
13449 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13450 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13451 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13452
13453 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13454 VectorFormat vform = instr->GetSVEVectorFormat();
13455
13456 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13457 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13458}
13459
13460void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013461 // This group only contains PNEXT, and there are no unallocated encodings.
13462 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13463 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13464
13465 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13466 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13467 VectorFormat vform = instr->GetSVEVectorFormat();
13468
13469 pnext(vform, pdn, pg, pdn);
13470 // TODO: Is this broken when pg == pdn?
13471 PredTest(vform, pg, pdn);
13472}
13473
13474void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13475 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080013476 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13477 LogicPRegister pg(ReadPRegister(instr->GetPn()));
13478 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013479 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13480 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013481 // Do nothing.
13482 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013483 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013484 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013485 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013486 default:
13487 VIXL_UNIMPLEMENTED();
13488 break;
13489 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013490
13491 LogicPRegister ffr(ReadFFR());
13492 mov_zeroing(pd, pg, ffr);
13493
13494 if (flags == SetFlags) {
13495 PredTest(kFormatVnB, pg, pd);
13496 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010013497}
13498
13499void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13500 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013501 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13502 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010013503 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013504 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080013505 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013506 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013507 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013508 VIXL_UNIMPLEMENTED();
13509 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013510 }
13511}
13512
13513void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013514 switch (instr->Mask(SVEPredicateTestMask)) {
13515 case PTEST_p_p:
13516 PredTest(kFormatVnB,
13517 ReadPRegister(instr->ExtractBits(13, 10)),
13518 ReadPRegister(instr->GetPn()));
13519 break;
13520 default:
13521 VIXL_UNIMPLEMENTED();
13522 break;
13523 }
13524}
13525
13526void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013527 switch (instr->Mask(SVEPredicateZeroMask)) {
13528 case PFALSE_p:
13529 pfalse(ReadPRegister(instr->GetPd()));
13530 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013531 default:
13532 VIXL_UNIMPLEMENTED();
13533 break;
13534 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013535}
13536
13537void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080013538 SimPRegister& pd = ReadPRegister(instr->GetPd());
13539 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13540 SimPRegister& pn = ReadPRegister(instr->GetPn());
13541 SimPRegister& pm = ReadPRegister(instr->GetPm());
13542
13543 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013544 switch (instr->Mask(SVEPropagateBreakMask)) {
13545 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013546 set_flags = true;
13547 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013548 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013549 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013550 break;
13551 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013552 set_flags = true;
13553 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013554 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013555 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013556 break;
13557 default:
13558 VIXL_UNIMPLEMENTED();
13559 break;
13560 }
TatWai Chong38303d92019-12-02 15:49:29 -080013561
13562 if (set_flags) {
13563 PredTest(kFormatVnB, pg, pd);
13564 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013565}
13566
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013567void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13568 uint64_t length = 0;
13569 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13570 case ADDPL_r_ri:
13571 length = GetPredicateLengthInBytes();
13572 break;
13573 case ADDVL_r_ri:
13574 length = GetVectorLengthInBytes();
13575 break;
13576 default:
13577 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013578 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013579 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013580 WriteXRegister(instr->GetRd(),
13581 base + (length * instr->GetImmSVEVLScale()),
13582 LogRegWrites,
13583 Reg31IsStackPointer);
13584}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013585
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013586void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13587 int64_t scale = instr->GetImmSVEVLScale();
13588
13589 switch (instr->Mask(SVEStackFrameSizeMask)) {
13590 case RDVL_r_i:
13591 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13592 break;
13593 default:
13594 VIXL_UNIMPLEMENTED();
13595 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013596}
13597
13598void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013599 // The only instruction in this group is `sel`, and there are no unused
13600 // encodings.
13601 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13602
13603 VectorFormat vform = instr->GetSVEVectorFormat();
13604 SimVRegister& zd = ReadVRegister(instr->GetRd());
13605 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13606 SimVRegister& zn = ReadVRegister(instr->GetRn());
13607 SimVRegister& zm = ReadVRegister(instr->GetRm());
13608
13609 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013610}
13611
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013612void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013613 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013614 case SETFFR_f: {
13615 LogicPRegister ffr(ReadFFR());
13616 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013617 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013618 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013619 default:
13620 VIXL_UNIMPLEMENTED();
13621 break;
13622 }
13623}
13624
13625void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013626 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013627 case WRFFR_f_p: {
13628 SimPRegister pn(ReadPRegister(instr->GetPn()));
13629 bool last_active = true;
13630 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13631 bool active = pn.GetBit(i);
13632 if (active && !last_active) {
13633 // `pn` is non-monotonic. This is UNPREDICTABLE.
13634 VIXL_ABORT();
13635 }
13636 last_active = active;
13637 }
13638 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013639 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013640 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013641 default:
13642 VIXL_UNIMPLEMENTED();
13643 break;
13644 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013645}
Alexandre Ramesd3832962016-07-04 15:03:43 +010013646
TatWai Chong6205eb42019-09-24 10:07:20 +010013647void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013648 bool is_signed;
13649 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13650 case LD1B_z_p_bi_u8:
13651 case LD1B_z_p_bi_u16:
13652 case LD1B_z_p_bi_u32:
13653 case LD1B_z_p_bi_u64:
13654 case LD1H_z_p_bi_u16:
13655 case LD1H_z_p_bi_u32:
13656 case LD1H_z_p_bi_u64:
13657 case LD1W_z_p_bi_u32:
13658 case LD1W_z_p_bi_u64:
13659 case LD1D_z_p_bi_u64:
13660 is_signed = false;
13661 break;
13662 case LD1SB_z_p_bi_s16:
13663 case LD1SB_z_p_bi_s32:
13664 case LD1SB_z_p_bi_s64:
13665 case LD1SH_z_p_bi_s32:
13666 case LD1SH_z_p_bi_s64:
13667 case LD1SW_z_p_bi_s64:
13668 is_signed = true;
13669 break;
13670 default:
13671 // This encoding group is complete, so no other values should be possible.
13672 VIXL_UNREACHABLE();
13673 is_signed = false;
13674 break;
13675 }
13676
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013677 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010013678 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13679 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013680 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13681 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13682 uint64_t offset =
13683 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013684 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013685 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013686 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13687 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013688 ReadPRegister(instr->GetPgLow8()),
13689 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013690 addr,
13691 is_signed);
13692}
13693
13694void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13695 const Instruction* instr) {
13696 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010013697 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13698 case LD1B_z_p_br_u8:
13699 case LD1B_z_p_br_u16:
13700 case LD1B_z_p_br_u32:
13701 case LD1B_z_p_br_u64:
13702 case LD1H_z_p_br_u16:
13703 case LD1H_z_p_br_u32:
13704 case LD1H_z_p_br_u64:
13705 case LD1W_z_p_br_u32:
13706 case LD1W_z_p_br_u64:
13707 case LD1D_z_p_br_u64:
13708 is_signed = false;
13709 break;
13710 case LD1SB_z_p_br_s16:
13711 case LD1SB_z_p_br_s32:
13712 case LD1SB_z_p_br_s64:
13713 case LD1SH_z_p_br_s32:
13714 case LD1SH_z_p_br_s64:
13715 case LD1SW_z_p_br_s64:
13716 is_signed = true;
13717 break;
13718 default:
13719 // This encoding group is complete, so no other values should be possible.
13720 VIXL_UNREACHABLE();
13721 is_signed = false;
13722 break;
13723 }
13724
13725 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13726 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13727 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13728 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13729 uint64_t offset = ReadXRegister(instr->GetRm());
13730 offset <<= msize_in_bytes_log2;
13731 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013732 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13733 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013734 ReadPRegister(instr->GetPgLow8()),
13735 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013736 addr,
13737 is_signed);
13738}
13739
Alexandre Ramesd3832962016-07-04 15:03:43 +010013740void Simulator::DoUnreachable(const Instruction* instr) {
13741 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13742 (instr->GetImmException() == kUnreachableOpcode));
13743
13744 fprintf(stream_,
13745 "Hit UNREACHABLE marker at pc=%p.\n",
13746 reinterpret_cast<const void*>(instr));
13747 abort();
13748}
13749
13750
13751void Simulator::DoTrace(const Instruction* instr) {
13752 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13753 (instr->GetImmException() == kTraceOpcode));
13754
13755 // Read the arguments encoded inline in the instruction stream.
13756 uint32_t parameters;
13757 uint32_t command;
13758
13759 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13760 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13761 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13762
13763 switch (command) {
13764 case TRACE_ENABLE:
13765 SetTraceParameters(GetTraceParameters() | parameters);
13766 break;
13767 case TRACE_DISABLE:
13768 SetTraceParameters(GetTraceParameters() & ~parameters);
13769 break;
13770 default:
13771 VIXL_UNREACHABLE();
13772 }
13773
13774 WritePc(instr->GetInstructionAtOffset(kTraceLength));
13775}
13776
13777
13778void Simulator::DoLog(const Instruction* instr) {
13779 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13780 (instr->GetImmException() == kLogOpcode));
13781
13782 // Read the arguments encoded inline in the instruction stream.
13783 uint32_t parameters;
13784
13785 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13786 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13787
13788 // We don't support a one-shot LOG_DISASM.
13789 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13790 // Print the requested information.
13791 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13792 if (parameters & LOG_REGS) PrintRegisters();
13793 if (parameters & LOG_VREGS) PrintVRegisters();
13794
13795 WritePc(instr->GetInstructionAtOffset(kLogLength));
13796}
13797
13798
13799void Simulator::DoPrintf(const Instruction* instr) {
13800 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13801 (instr->GetImmException() == kPrintfOpcode));
13802
13803 // Read the arguments encoded inline in the instruction stream.
13804 uint32_t arg_count;
13805 uint32_t arg_pattern_list;
13806 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13807 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13808 memcpy(&arg_pattern_list,
13809 instr + kPrintfArgPatternListOffset,
13810 sizeof(arg_pattern_list));
13811
13812 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13813 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13814
13815 // We need to call the host printf function with a set of arguments defined by
13816 // arg_pattern_list. Because we don't know the types and sizes of the
13817 // arguments, this is very difficult to do in a robust and portable way. To
13818 // work around the problem, we pick apart the format string, and print one
13819 // format placeholder at a time.
13820
13821 // Allocate space for the format string. We take a copy, so we can modify it.
13822 // Leave enough space for one extra character per expected argument (plus the
13823 // '\0' termination).
13824 const char* format_base = ReadRegister<const char*>(0);
13825 VIXL_ASSERT(format_base != NULL);
13826 size_t length = strlen(format_base) + 1;
13827 char* const format = new char[length + arg_count];
13828
13829 // A list of chunks, each with exactly one format placeholder.
13830 const char* chunks[kPrintfMaxArgCount];
13831
13832 // Copy the format string and search for format placeholders.
13833 uint32_t placeholder_count = 0;
13834 char* format_scratch = format;
13835 for (size_t i = 0; i < length; i++) {
13836 if (format_base[i] != '%') {
13837 *format_scratch++ = format_base[i];
13838 } else {
13839 if (format_base[i + 1] == '%') {
13840 // Ignore explicit "%%" sequences.
13841 *format_scratch++ = format_base[i];
13842 i++;
13843 // Chunks after the first are passed as format strings to printf, so we
13844 // need to escape '%' characters in those chunks.
13845 if (placeholder_count > 0) *format_scratch++ = format_base[i];
13846 } else {
13847 VIXL_CHECK(placeholder_count < arg_count);
13848 // Insert '\0' before placeholders, and store their locations.
13849 *format_scratch++ = '\0';
13850 chunks[placeholder_count++] = format_scratch;
13851 *format_scratch++ = format_base[i];
13852 }
13853 }
13854 }
13855 VIXL_CHECK(placeholder_count == arg_count);
13856
13857 // Finally, call printf with each chunk, passing the appropriate register
13858 // argument. Normally, printf returns the number of bytes transmitted, so we
13859 // can emulate a single printf call by adding the result from each chunk. If
13860 // any call returns a negative (error) value, though, just return that value.
13861
13862 printf("%s", clr_printf);
13863
13864 // Because '\0' is inserted before each placeholder, the first string in
13865 // 'format' contains no format placeholders and should be printed literally.
13866 int result = printf("%s", format);
13867 int pcs_r = 1; // Start at x1. x0 holds the format string.
13868 int pcs_f = 0; // Start at d0.
13869 if (result >= 0) {
13870 for (uint32_t i = 0; i < placeholder_count; i++) {
13871 int part_result = -1;
13872
13873 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13874 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13875 switch (arg_pattern) {
13876 case kPrintfArgW:
13877 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13878 break;
13879 case kPrintfArgX:
13880 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13881 break;
13882 case kPrintfArgD:
13883 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13884 break;
13885 default:
13886 VIXL_UNREACHABLE();
13887 }
13888
13889 if (part_result < 0) {
13890 // Handle error values.
13891 result = part_result;
13892 break;
13893 }
13894
13895 result += part_result;
13896 }
13897 }
13898
13899 printf("%s", clr_normal);
13900
13901 // Printf returns its result in x0 (just like the C library's printf).
13902 WriteXRegister(0, result);
13903
13904 // The printf parameters are inlined in the code, so skip them.
13905 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13906
13907 // Set LR as if we'd just called a native printf function.
13908 WriteLr(ReadPc());
13909
13910 delete[] format;
13911}
13912
Alexandre Rames064e02d2016-07-12 11:53:13 +010013913
Alexandre Ramesca73ba02016-07-28 09:16:03 +010013914#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010013915void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013916 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013917 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13918 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013919 uintptr_t call_wrapper_address =
13920 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13921 uintptr_t function_address =
13922 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080013923 RuntimeCallType call_type = static_cast<RuntimeCallType>(
13924 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013925 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010013926 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013927
13928 if (call_type == kCallRuntime) {
13929 WriteRegister(kLinkRegCode,
13930 instr->GetInstructionAtOffset(kRuntimeCallLength));
13931 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013932 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013933 // Read the return address from `lr` and write it into `pc`.
13934 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013935}
13936#else
13937void Simulator::DoRuntimeCall(const Instruction* instr) {
13938 USE(instr);
13939 VIXL_UNREACHABLE();
13940}
13941#endif
13942
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013943
13944void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
13945 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
13946
13947 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013948 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013949 std::numeric_limits<ElementType>::max());
13950
13951 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
13952
13953 size_t element_size = sizeof(ElementType);
13954 size_t offset = kConfigureCPUFeaturesListOffset;
13955
13956 // Read the kNone-terminated list of features.
13957 CPUFeatures parameters;
13958 while (true) {
13959 ElementType feature = Memory::Read<ElementType>(instr + offset);
13960 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013961 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013962 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
13963 }
13964
13965 switch (instr->GetImmException()) {
13966 case kSetCPUFeaturesOpcode:
13967 SetCPUFeatures(parameters);
13968 break;
13969 case kEnableCPUFeaturesOpcode:
13970 GetCPUFeatures()->Combine(parameters);
13971 break;
13972 case kDisableCPUFeaturesOpcode:
13973 GetCPUFeatures()->Remove(parameters);
13974 break;
13975 default:
13976 VIXL_UNREACHABLE();
13977 break;
13978 }
13979
13980 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
13981}
13982
13983
13984void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
13985 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13986 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
13987 USE(instr);
13988
13989 saved_cpu_features_.push_back(*GetCPUFeatures());
13990}
13991
13992
13993void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
13994 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13995 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
13996 USE(instr);
13997
13998 SetCPUFeatures(saved_cpu_features_.back());
13999 saved_cpu_features_.pop_back();
14000}
14001
14002
Alexandre Ramesd3832962016-07-04 15:03:43 +010014003} // namespace aarch64
14004} // namespace vixl
14005
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010014006#endif // VIXL_INCLUDE_SIMULATOR_AARCH64