blob: b2cedaf506e4b0c581be0ec45c665ae5cc802fa1 [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},
TatWai Chongada6b352020-11-06 13:48:09 -080088 {"cmla_z_zzz", &Simulator::SimulateSVEComplexIntMulAdd},
TatWai Chong6b67f6e2020-12-03 23:37:57 -080089 {"cmla_z_zzzi_h", &Simulator::SimulateSVEComplexIntMulAdd},
90 {"cmla_z_zzzi_s", &Simulator::SimulateSVEComplexIntMulAdd},
Martyn Capewellb1b95782020-10-23 15:59:49 +010091 {"eor3_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +010092 {"eorbt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
93 {"eortb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
94 {"ext_z_zi_con", &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm},
95 {"faddp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
96 {"fcvtlt_z_p_z_h2s", &Simulator::Simulate_ZdS_PgM_ZnH},
97 {"fcvtlt_z_p_z_s2d", &Simulator::Simulate_ZdD_PgM_ZnS},
98 {"fcvtnt_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
99 {"fcvtnt_z_p_z_s2h", &Simulator::Simulate_ZdH_PgM_ZnS},
100 {"fcvtx_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
101 {"fcvtxnt_z_p_z_d2s", &Simulator::Simulate_ZdS_PgM_ZnD},
102 {"flogb_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
103 {"fmaxnmp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
104 {"fmaxp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
105 {"fminnmp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
106 {"fminp_z_p_zz", &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
107 {"fmlalb_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
108 {"fmlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
109 {"fmlalt_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
110 {"fmlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
111 {"fmlslb_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
112 {"fmlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
113 {"fmlslt_z_zzz", &Simulator::Simulate_ZdaS_ZnH_ZmH},
114 {"fmlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
115 {"histcnt_z_p_zz", &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT},
116 {"histseg_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
117 {"ldnt1b_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
118 {"ldnt1b_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
119 {"ldnt1d_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
120 {"ldnt1h_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
121 {"ldnt1h_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
122 {"ldnt1sb_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
123 {"ldnt1sb_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
124 {"ldnt1sh_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
125 {"ldnt1sh_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
126 {"ldnt1sw_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
127 {"ldnt1w_z_p_ar_d_64_unscaled", &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
128 {"ldnt1w_z_p_ar_s_x32_unscaled", &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
129 {"match_p_p_zz", &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
Martyn Capewell8f4e1692020-11-06 14:16:14 +0000130 {"mla_z_zzzi_d", &Simulator::SimulateSVEMlaMlsIndex},
131 {"mla_z_zzzi_h", &Simulator::SimulateSVEMlaMlsIndex},
132 {"mla_z_zzzi_s", &Simulator::SimulateSVEMlaMlsIndex},
133 {"mls_z_zzzi_d", &Simulator::SimulateSVEMlaMlsIndex},
134 {"mls_z_zzzi_h", &Simulator::SimulateSVEMlaMlsIndex},
135 {"mls_z_zzzi_s", &Simulator::SimulateSVEMlaMlsIndex},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100136 {"mul_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
Martyn Capewellf272b9c2020-11-05 18:30:16 +0000137 {"mul_z_zzi_d", &Simulator::SimulateSVEMulIndex},
138 {"mul_z_zzi_h", &Simulator::SimulateSVEMulIndex},
139 {"mul_z_zzi_s", &Simulator::SimulateSVEMulIndex},
Martyn Capewellb1b95782020-10-23 15:59:49 +0100140 {"nbsl_z_zzz", &Simulator::SimulateSVEBitwiseTernary},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100141 {"nmatch_p_p_zz", &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
142 {"pmul_z_zz", &Simulator::Simulate_ZdB_ZnB_ZmB},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700143 {"pmullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
144 {"pmullt_z_zz", &Simulator::SimulateSVEIntMulLongVec},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +0100145 {"raddhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
146 {"raddhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100147 {"rshrnb_z_zi", &Simulator::SimulateSVENarrow},
148 {"rshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell8b9c44b2020-10-14 18:21:42 +0100149 {"rsubhnb_z_zz", &Simulator::SimulateSVEAddSubHigh},
150 {"rsubhnt_z_zz", &Simulator::SimulateSVEAddSubHigh},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100151 {"saba_z_zzz", &Simulator::Simulate_ZdaT_ZnT_ZmT},
Martyn Capewell67d2f822020-10-13 16:39:33 +0100152 {"sabalb_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
153 {"sabalt_z_zzz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100154 {"sabdlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
155 {"sabdlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100156 {"sadalp_z_p_z", &Simulator::Simulate_ZdaT_PgM_ZnTb},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100157 {"saddlb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
158 {"saddlbt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
159 {"saddlt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100160 {"saddwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
161 {"saddwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100162 {"sbclb_z_zzz", &Simulator::SimulateSVEAddSubCarry},
163 {"sbclt_z_zzz", &Simulator::SimulateSVEAddSubCarry},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100164 {"shadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100165 {"shrnb_z_zi", &Simulator::SimulateSVENarrow},
166 {"shrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100167 {"shsub_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
168 {"shsubr_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100169 {"sli_z_zzi", &Simulator::Simulate_ZdT_ZnT_const},
Martyn Capewellfa1e2112020-09-16 16:53:09 +0100170 {"smaxp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
171 {"sminp_z_p_zz", &Simulator::SimulateSVEIntArithPair},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100172 {"smlalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000173 {"smlalb_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
174 {"smlalb_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100175 {"smlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000176 {"smlalt_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
177 {"smlalt_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100178 {"smlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000179 {"smlslb_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
180 {"smlslb_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100181 {"smlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000182 {"smlslt_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
183 {"smlslt_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100184 {"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 Capewell2e66dc72020-12-02 17:59:09 +0000187 {"smullb_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
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 Capewell2e66dc72020-12-02 17:59:09 +0000190 {"smullt_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +0000191 {"splice_z_p_zz_con", &Simulator::VisitSVEVectorSplice},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100192 {"sqabs_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
Martyn Capewell9b532192020-09-15 16:20:11 +0100193 {"sqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100194 {"sqcadd_z_zz", &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
195 {"sqdmlalb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
196 {"sqdmlalb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
197 {"sqdmlalb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
198 {"sqdmlalbt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
199 {"sqdmlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
200 {"sqdmlalt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
201 {"sqdmlalt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
202 {"sqdmlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
203 {"sqdmlslb_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
204 {"sqdmlslb_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
205 {"sqdmlslbt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
206 {"sqdmlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
207 {"sqdmlslt_z_zzzi_d", &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
208 {"sqdmlslt_z_zzzi_s", &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
209 {"sqdmulh_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmT},
210 {"sqdmulh_z_zzi_d", &Simulator::Simulate_ZdD_ZnD_ZmD_imm},
211 {"sqdmulh_z_zzi_h", &Simulator::Simulate_ZdH_ZnH_ZmH_imm},
212 {"sqdmulh_z_zzi_s", &Simulator::Simulate_ZdS_ZnS_ZmS_imm},
TatWai Chong236e7ae2020-09-13 14:55:04 -0700213 {"sqdmullb_z_zz", &Simulator::SimulateSVEIntMulLongVec},
TatWai Chong1719b712020-09-25 18:16:40 -0700214 {"sqdmullb_z_zzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000215 {"sqdmullb_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
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 Capewell2e66dc72020-12-02 17:59:09 +0000218 {"sqdmullt_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100219 {"sqneg_z_p_z", &Simulator::Simulate_ZdT_PgM_ZnT},
TatWai Chongada6b352020-11-06 13:48:09 -0800220 {"sqrdcmlah_z_zzz", &Simulator::SimulateSVEComplexIntMulAdd},
TatWai Chong6b67f6e2020-12-03 23:37:57 -0800221 {"sqrdcmlah_z_zzzi_h", &Simulator::SimulateSVEComplexIntMulAdd},
222 {"sqrdcmlah_z_zzzi_s", &Simulator::SimulateSVEComplexIntMulAdd},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100223 {"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},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000298 {"umlalb_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
299 {"umlalb_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100300 {"umlalt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000301 {"umlalt_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
302 {"umlalt_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100303 {"umlslb_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000304 {"umlslb_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
305 {"umlslb_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100306 {"umlslt_z_zzz", &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
Martyn Capewell2e66dc72020-12-02 17:59:09 +0000307 {"umlslt_z_zzzi_d", &Simulator::SimulateSVESaturatingIntMulLongIdx},
308 {"umlslt_z_zzzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100309 {"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 Capewell2e66dc72020-12-02 17:59:09 +0000312 {"umullb_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
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 Capewell2e66dc72020-12-02 17:59:09 +0000315 {"umullt_z_zzi_s", &Simulator::SimulateSVESaturatingIntMulLongIdx},
Martyn Capewell9b532192020-09-15 16:20:11 +0100316 {"uqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100317 {"uqrshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
318 {"uqrshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100319 {"uqrshrnb_z_zi", &Simulator::SimulateSVENarrow},
320 {"uqrshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100321 {"uqshl_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100322 {"uqshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
323 {"uqshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100324 {"uqshrnb_z_zi", &Simulator::SimulateSVENarrow},
325 {"uqshrnt_z_zi", &Simulator::SimulateSVENarrow},
Martyn Capewell9b532192020-09-15 16:20:11 +0100326 {"uqsub_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
327 {"uqsubr_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100328 {"uqxtnb_z_zz", &Simulator::SimulateSVENarrow},
329 {"uqxtnt_z_zz", &Simulator::SimulateSVENarrow},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100330 {"urecpe_z_p_z", &Simulator::Simulate_ZdS_PgM_ZnS},
Martyn Capewell4e1980d2020-09-04 11:22:41 +0100331 {"urhadd_z_p_zz", &Simulator::SimulateSVEHalvingAddSub},
Martyn Capewell42bd8e92020-09-09 18:34:44 +0100332 {"urshl_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
333 {"urshlr_z_p_zz", &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100334 {"urshr_z_p_zi", &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
335 {"ursqrte_z_p_z", &Simulator::Simulate_ZdS_PgM_ZnS},
336 {"ursra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
Martyn Capewellea9b4072020-10-09 11:25:26 +0100337 {"ushllb_z_zi", &Simulator::SimulateSVEShiftLeftImm},
338 {"ushllt_z_zi", &Simulator::SimulateSVEShiftLeftImm},
Martyn Capewell9b532192020-09-15 16:20:11 +0100339 {"usqadd_z_p_zz", &Simulator::SimulateSVESaturatingArithmetic},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100340 {"usra_z_zi", &Simulator::Simulate_ZdaT_ZnT_const},
Martyn Capewellc7275e62020-09-24 14:06:07 +0100341 {"usublb_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
342 {"usublt_z_zz", &Simulator::SimulateSVEInterleavedArithLong},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100343 {"usubwb_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
344 {"usubwt_z_zz", &Simulator::Simulate_ZdT_ZnT_ZmTb},
Martyn Capewellf0844012020-10-23 16:38:26 +0100345 {"whilege_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
346 {"whilegt_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
347 {"whilehi_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
348 {"whilehs_p_p_rr", &Simulator::VisitSVEIntCompareScalarCountAndLimit},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100349 {"whilerw_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
350 {"whilewr_p_rr", &Simulator::Simulate_PdT_Xn_Xm},
Martyn Capewell97ca8062020-10-23 14:45:14 +0100351 {"xar_z_zzi", &Simulator::SimulateSVEExclusiveOrRotate},
Martyn Capewell6bf28752020-08-05 11:57:06 +0100352};
Martyn Capewell8c691852020-07-15 18:33:15 +0100353
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100354Simulator::Simulator(Decoder* decoder, FILE* stream)
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +0100355 : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100356 // Ensure that shift operations act as the simulator expects.
357 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
358 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
359
Jacob Bramley85a9c102019-12-09 17:48:29 +0000360 // Set up a dummy pipe for CanReadMemory.
361 VIXL_CHECK(pipe(dummy_pipe_fd_) == 0);
362
Alexandre Ramesd3832962016-07-04 15:03:43 +0100363 // Set up the decoder.
364 decoder_ = decoder;
365 decoder_->AppendVisitor(this);
366
367 stream_ = stream;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100368
Alexandre Ramesd3832962016-07-04 15:03:43 +0100369 print_disasm_ = new PrintDisassembler(stream_);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100370 // The Simulator and Disassembler share the same available list, held by the
371 // auditor. The Disassembler only annotates instructions with features that
372 // are _not_ available, so registering the auditor should have no effect
373 // unless the simulator is about to abort (due to missing features). In
374 // practice, this means that with trace enabled, the simulator will crash just
375 // after the disassembler prints the instruction, with the missing features
376 // enumerated.
377 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
378
Alexandre Ramesd3832962016-07-04 15:03:43 +0100379 SetColouredTrace(false);
380 trace_parameters_ = LOG_NONE;
381
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100382 // We have to configure the SVE vector register length before calling
383 // ResetState().
384 SetVectorLengthInBits(kZRegMinSize);
385
Alexandre Ramesd3832962016-07-04 15:03:43 +0100386 ResetState();
387
388 // Allocate and set up the simulator stack.
389 stack_ = new byte[stack_size_];
390 stack_limit_ = stack_ + stack_protection_size_;
391 // Configure the starting stack pointer.
392 // - Find the top of the stack.
393 byte* tos = stack_ + stack_size_;
394 // - There's a protection region at both ends of the stack.
395 tos -= stack_protection_size_;
396 // - The stack pointer must be 16-byte aligned.
397 tos = AlignDown(tos, 16);
398 WriteSp(tos);
399
Alexandre Ramesd3832962016-07-04 15:03:43 +0100400 // Print a warning about exclusive-access instructions, but only the first
401 // time they are encountered. This warning can be silenced using
402 // SilenceExclusiveAccessWarning().
403 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100404
405 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800406
407 // Initialize the common state of RNDR and RNDRRS.
408 uint16_t seed[3] = {11, 22, 33};
Jacob Bramley85a9c102019-12-09 17:48:29 +0000409 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
410 memcpy(rand_state_, seed, sizeof(rand_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700411
412 // Initialize all bits of pseudo predicate register to true.
413 LogicPRegister ones(pregister_all_true_);
414 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100415}
416
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100417void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100418 // Reset the system registers.
419 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
420 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
TatWai Chong4023d7a2019-11-18 14:16:28 -0800421 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100422}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100423
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100424void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100425 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
426 WriteXRegister(i, 0xbadbeef);
427 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100428 // Returning to address 0 exits the Simulator.
429 WriteLr(kEndOfSimAddress);
430}
Pierre Langlois23703a72016-08-15 17:23:39 +0100431
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100432void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800433 // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100434 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
435 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800436 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100437 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100438 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100439 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800440 // Encode the register number and (D-sized) lane into each NaN, to
441 // make them easier to trace.
442 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
443 (0x0000000000000001 * lane);
444 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
445 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100446 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800447 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100448 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100449}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800450
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100451void Simulator::ResetPRegisters() {
452 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
453 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
454 // Ensure the register configuration fits in this bit encoding.
455 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
456 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700457 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100458 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
459 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700460 // Encode the register number and (H-sized) lane into each lane slot.
461 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100462 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700463 }
464 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100465}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700466
TatWai Chong4023d7a2019-11-18 14:16:28 -0800467void Simulator::ResetFFR() {
468 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
469 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
470 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
471}
472
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100473void Simulator::ResetState() {
474 ResetSystemRegisters();
475 ResetRegisters();
476 ResetVRegisters();
477 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100478
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100479 pc_ = NULL;
480 pc_modified_ = false;
481
482 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100483 btype_ = DefaultBType;
484 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100485}
486
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100487void Simulator::SetVectorLengthInBits(unsigned vector_length) {
488 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
489 (vector_length <= kZRegMaxSize));
490 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
491 vector_length_ = vector_length;
492
493 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
494 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
495 }
496 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
497 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
498 }
499
TatWai Chong4023d7a2019-11-18 14:16:28 -0800500 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
501
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100502 ResetVRegisters();
503 ResetPRegisters();
TatWai Chong4023d7a2019-11-18 14:16:28 -0800504 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100505}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100506
507Simulator::~Simulator() {
508 delete[] stack_;
509 // The decoder may outlive the simulator.
510 decoder_->RemoveVisitor(print_disasm_);
511 delete print_disasm_;
Jacob Bramley85a9c102019-12-09 17:48:29 +0000512 close(dummy_pipe_fd_[0]);
513 close(dummy_pipe_fd_[1]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100514}
515
516
517void Simulator::Run() {
518 // Flush any written registers before executing anything, so that
519 // manually-set registers are logged _before_ the first instruction.
520 LogAllWrittenRegisters();
521
522 while (pc_ != kEndOfSimAddress) {
523 ExecuteInstruction();
524 }
525}
526
527
528void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100529 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100530 Run();
531}
532
533
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100534// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100535const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
536 "x6", "x7", "x8", "x9", "x10", "x11",
537 "x12", "x13", "x14", "x15", "x16", "x17",
538 "x18", "x19", "x20", "x21", "x22", "x23",
539 "x24", "x25", "x26", "x27", "x28", "x29",
540 "lr", "xzr", "sp"};
541
542const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
543 "w6", "w7", "w8", "w9", "w10", "w11",
544 "w12", "w13", "w14", "w15", "w16", "w17",
545 "w18", "w19", "w20", "w21", "w22", "w23",
546 "w24", "w25", "w26", "w27", "w28", "w29",
547 "w30", "wzr", "wsp"};
548
Jacob Bramley423e5422019-11-13 19:15:55 +0000549const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
550 "b6", "b7", "b8", "b9", "b10", "b11",
551 "b12", "b13", "b14", "b15", "b16", "b17",
552 "b18", "b19", "b20", "b21", "b22", "b23",
553 "b24", "b25", "b26", "b27", "b28", "b29",
554 "b30", "b31"};
555
Carey Williamsd8bb3572018-04-10 11:58:07 +0100556const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
557 "h6", "h7", "h8", "h9", "h10", "h11",
558 "h12", "h13", "h14", "h15", "h16", "h17",
559 "h18", "h19", "h20", "h21", "h22", "h23",
560 "h24", "h25", "h26", "h27", "h28", "h29",
561 "h30", "h31"};
562
Alexandre Ramesd3832962016-07-04 15:03:43 +0100563const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
564 "s6", "s7", "s8", "s9", "s10", "s11",
565 "s12", "s13", "s14", "s15", "s16", "s17",
566 "s18", "s19", "s20", "s21", "s22", "s23",
567 "s24", "s25", "s26", "s27", "s28", "s29",
568 "s30", "s31"};
569
570const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
571 "d6", "d7", "d8", "d9", "d10", "d11",
572 "d12", "d13", "d14", "d15", "d16", "d17",
573 "d18", "d19", "d20", "d21", "d22", "d23",
574 "d24", "d25", "d26", "d27", "d28", "d29",
575 "d30", "d31"};
576
577const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
578 "v6", "v7", "v8", "v9", "v10", "v11",
579 "v12", "v13", "v14", "v15", "v16", "v17",
580 "v18", "v19", "v20", "v21", "v22", "v23",
581 "v24", "v25", "v26", "v27", "v28", "v29",
582 "v30", "v31"};
583
TatWai Chong72d2e562019-05-16 11:22:22 -0700584const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
585 "z6", "z7", "z8", "z9", "z10", "z11",
586 "z12", "z13", "z14", "z15", "z16", "z17",
587 "z18", "z19", "z20", "z21", "z22", "z23",
588 "z24", "z25", "z26", "z27", "z28", "z29",
589 "z30", "z31"};
590
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100591const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
592 "p6", "p7", "p8", "p9", "p10", "p11",
593 "p12", "p13", "p14", "p15"};
594// clang-format on
595
Alexandre Ramesd3832962016-07-04 15:03:43 +0100596
597const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100598 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000599 if ((code == kSPRegInternalCode) ||
600 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100601 code = kZeroRegCode + 1;
602 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000603 VIXL_ASSERT(code < ArrayLength(wreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100604 return wreg_names[code];
605}
606
607
608const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100609 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000610 if ((code == kSPRegInternalCode) ||
611 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100612 code = kZeroRegCode + 1;
613 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000614 VIXL_ASSERT(code < ArrayLength(xreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100615 return xreg_names[code];
616}
617
618
Jacob Bramley423e5422019-11-13 19:15:55 +0000619const char* Simulator::BRegNameForCode(unsigned code) {
620 VIXL_ASSERT(code < kNumberOfVRegisters);
621 return breg_names[code];
622}
623
624
Carey Williamsd8bb3572018-04-10 11:58:07 +0100625const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100626 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100627 return hreg_names[code];
628}
629
630
Alexandre Ramesd3832962016-07-04 15:03:43 +0100631const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100632 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100633 return sreg_names[code];
634}
635
636
637const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100638 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100639 return dreg_names[code];
640}
641
642
643const char* Simulator::VRegNameForCode(unsigned code) {
644 VIXL_ASSERT(code < kNumberOfVRegisters);
645 return vreg_names[code];
646}
647
648
TatWai Chong72d2e562019-05-16 11:22:22 -0700649const char* Simulator::ZRegNameForCode(unsigned code) {
650 VIXL_ASSERT(code < kNumberOfZRegisters);
651 return zreg_names[code];
652}
653
654
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100655const char* Simulator::PRegNameForCode(unsigned code) {
656 VIXL_ASSERT(code < kNumberOfPRegisters);
657 return preg_names[code];
658}
659
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000660SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
661 SimVRegister ones, result;
662 dup_immediate(kFormatVnB, ones, 0xff);
663 mov_zeroing(kFormatVnB, result, pg, ones);
664 return result;
665}
666
TatWai Chong47c26842020-02-10 01:51:32 -0800667void Simulator::ExtractFromSimVRegister(VectorFormat vform,
668 SimPRegister& pd,
669 SimVRegister vreg) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000670 SimVRegister zero;
671 dup_immediate(kFormatVnB, zero, 0);
672 SVEIntCompareVectorsHelper(ne,
TatWai Chong47c26842020-02-10 01:51:32 -0800673 vform,
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000674 pd,
675 GetPTrue(),
676 vreg,
677 zero,
678 false,
679 LeaveFlags);
680}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100681
Alexandre Ramesd3832962016-07-04 15:03:43 +0100682#define COLOUR(colour_code) "\033[0;" colour_code "m"
683#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100684#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100685#define NORMAL ""
686#define GREY "30"
687#define RED "31"
688#define GREEN "32"
689#define YELLOW "33"
690#define BLUE "34"
691#define MAGENTA "35"
692#define CYAN "36"
693#define WHITE "37"
694void Simulator::SetColouredTrace(bool value) {
695 coloured_trace_ = value;
696
697 clr_normal = value ? COLOUR(NORMAL) : "";
698 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
699 clr_flag_value = value ? COLOUR(NORMAL) : "";
700 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
701 clr_reg_value = value ? COLOUR(CYAN) : "";
702 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
703 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100704 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
705 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100706 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
707 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
708 clr_warning_message = value ? COLOUR(YELLOW) : "";
709 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100710 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100711
712 if (value) {
713 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
714 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
715 } else {
716 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
717 print_disasm_->SetCPUFeaturesSuffix("");
718 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100719}
720
721
722void Simulator::SetTraceParameters(int parameters) {
723 bool disasm_before = trace_parameters_ & LOG_DISASM;
724 trace_parameters_ = parameters;
725 bool disasm_after = trace_parameters_ & LOG_DISASM;
726
727 if (disasm_before != disasm_after) {
728 if (disasm_after) {
729 decoder_->InsertVisitorBefore(print_disasm_, this);
730 } else {
731 decoder_->RemoveVisitor(print_disasm_);
732 }
733 }
734}
735
736
Alexandre Ramesd3832962016-07-04 15:03:43 +0100737// Helpers ---------------------------------------------------------------------
738uint64_t Simulator::AddWithCarry(unsigned reg_size,
739 bool set_flags,
740 uint64_t left,
741 uint64_t right,
742 int carry_in) {
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100743 std::pair<uint64_t, uint8_t> result_and_flags =
744 AddWithCarry(reg_size, left, right, carry_in);
745 if (set_flags) {
746 uint8_t flags = result_and_flags.second;
747 ReadNzcv().SetN((flags >> 3) & 1);
748 ReadNzcv().SetZ((flags >> 2) & 1);
749 ReadNzcv().SetC((flags >> 1) & 1);
750 ReadNzcv().SetV((flags >> 0) & 1);
751 LogSystemRegister(NZCV);
752 }
753 return result_and_flags.first;
754}
755
756std::pair<uint64_t, uint8_t> Simulator::AddWithCarry(unsigned reg_size,
757 uint64_t left,
758 uint64_t right,
759 int carry_in) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100760 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
761 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
762
763 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
764 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
765 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
766
767 left &= reg_mask;
768 right &= reg_mask;
769 uint64_t result = (left + right + carry_in) & reg_mask;
770
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100771 // NZCV bits, ordered N in bit 3 to V in bit 0.
772 uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0;
773 nzcv |= CalcZFlag(result) ? 4 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100774
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100775 // Compute the C flag by comparing the result to the max unsigned integer.
776 uint64_t max_uint_2op = max_uint - carry_in;
777 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
778 nzcv |= C ? 2 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100779
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100780 // Overflow iff the sign bit is the same for the two inputs and different
781 // for the result.
782 uint64_t left_sign = left & sign_mask;
783 uint64_t right_sign = right & sign_mask;
784 uint64_t result_sign = result & sign_mask;
785 bool V = (left_sign == right_sign) && (left_sign != result_sign);
786 nzcv |= V ? 1 : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100787
Martyn Capewellc4b56bb2020-10-14 15:45:14 +0100788 return std::make_pair(result, nzcv);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100789}
790
Alexandre Ramesd3832962016-07-04 15:03:43 +0100791int64_t Simulator::ShiftOperand(unsigned reg_size,
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000792 uint64_t uvalue,
Alexandre Ramesd3832962016-07-04 15:03:43 +0100793 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100794 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800795 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
796 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000797 if (amount > 0) {
798 uint64_t mask = GetUintMask(reg_size);
799 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
800 // The behavior is undefined in c++ if the shift amount greater than or
801 // equal to the register lane size. Work out the shifted result based on
802 // architectural behavior before performing the c++ type shfit operations.
803 switch (shift_type) {
804 case LSL:
805 if (amount >= reg_size) {
806 return UINT64_C(0);
807 }
808 uvalue <<= amount;
809 break;
810 case LSR:
811 if (amount >= reg_size) {
812 return UINT64_C(0);
813 }
814 uvalue >>= amount;
815 break;
816 case ASR:
817 if (amount >= reg_size) {
818 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
819 }
820 uvalue >>= amount;
821 if (is_negative) {
822 // Simulate sign-extension to 64 bits.
823 uvalue |= ~UINT64_C(0) << (reg_size - amount);
824 }
825 break;
826 case ROR: {
827 uvalue = RotateRight(uvalue, amount, reg_size);
828 break;
TatWai Chong29a0c432019-11-06 22:20:44 -0800829 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000830 default:
831 VIXL_UNIMPLEMENTED();
832 return 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100833 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000834 uvalue &= mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100835 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000836
837 int64_t result;
838 memcpy(&result, &uvalue, sizeof(result));
839 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100840}
841
842
843int64_t Simulator::ExtendValue(unsigned reg_size,
844 int64_t value,
845 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100846 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100847 switch (extend_type) {
848 case UXTB:
849 value &= kByteMask;
850 break;
851 case UXTH:
852 value &= kHalfWordMask;
853 break;
854 case UXTW:
855 value &= kWordMask;
856 break;
857 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000858 value &= kByteMask;
859 if ((value & 0x80) != 0) {
860 value |= ~UINT64_C(0) << 8;
861 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100862 break;
863 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000864 value &= kHalfWordMask;
865 if ((value & 0x8000) != 0) {
866 value |= ~UINT64_C(0) << 16;
867 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100868 break;
869 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000870 value &= kWordMask;
871 if ((value & 0x80000000) != 0) {
872 value |= ~UINT64_C(0) << 32;
873 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100874 break;
875 case UXTX:
876 case SXTX:
877 break;
878 default:
879 VIXL_UNREACHABLE();
880 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000881 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100882}
883
884
885void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
886 AssertSupportedFPCR();
887
888 // TODO: This assumes that the C++ implementation handles comparisons in the
889 // way that we expect (as per AssertSupportedFPCR()).
890 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100891 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100892 ReadNzcv().SetRawValue(FPUnorderedFlag);
893 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
894 (trap == EnableTrap)) {
895 process_exception = true;
896 }
897 } else if (val0 < val1) {
898 ReadNzcv().SetRawValue(FPLessThanFlag);
899 } else if (val0 > val1) {
900 ReadNzcv().SetRawValue(FPGreaterThanFlag);
901 } else if (val0 == val1) {
902 ReadNzcv().SetRawValue(FPEqualFlag);
903 } else {
904 VIXL_UNREACHABLE();
905 }
906 LogSystemRegister(NZCV);
907 if (process_exception) FPProcessException();
908}
909
910
Alexandre Rames868bfc42016-07-19 17:10:48 +0100911uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
912 VIXL_ASSERT(mem_op.IsValid());
913 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
914 if (mem_op.IsImmediateOffset()) {
915 return base + mem_op.GetOffset();
916 } else {
917 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
918 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100919 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100920 if (mem_op.GetShift() != NO_SHIFT) {
921 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
922 }
923 if (mem_op.GetExtend() != NO_EXTEND) {
924 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
925 }
926 return static_cast<uint64_t>(base + offset);
927 }
928}
929
930
Alexandre Ramesd3832962016-07-04 15:03:43 +0100931Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
932 unsigned reg_size, unsigned lane_size) {
933 VIXL_ASSERT(reg_size >= lane_size);
934
935 uint32_t format = 0;
936 if (reg_size != lane_size) {
937 switch (reg_size) {
938 default:
939 VIXL_UNREACHABLE();
940 break;
941 case kQRegSizeInBytes:
942 format = kPrintRegAsQVector;
943 break;
944 case kDRegSizeInBytes:
945 format = kPrintRegAsDVector;
946 break;
947 }
948 }
949
950 switch (lane_size) {
951 default:
952 VIXL_UNREACHABLE();
953 break;
954 case kQRegSizeInBytes:
955 format |= kPrintReg1Q;
956 break;
957 case kDRegSizeInBytes:
958 format |= kPrintReg1D;
959 break;
960 case kSRegSizeInBytes:
961 format |= kPrintReg1S;
962 break;
963 case kHRegSizeInBytes:
964 format |= kPrintReg1H;
965 break;
966 case kBRegSizeInBytes:
967 format |= kPrintReg1B;
968 break;
969 }
970 // These sizes would be duplicate case labels.
971 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
972 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
973 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
974 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
975
976 return static_cast<PrintRegisterFormat>(format);
977}
978
979
980Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
981 VectorFormat vform) {
982 switch (vform) {
983 default:
984 VIXL_UNREACHABLE();
985 return kPrintReg16B;
986 case kFormat16B:
987 return kPrintReg16B;
988 case kFormat8B:
989 return kPrintReg8B;
990 case kFormat8H:
991 return kPrintReg8H;
992 case kFormat4H:
993 return kPrintReg4H;
994 case kFormat4S:
995 return kPrintReg4S;
996 case kFormat2S:
997 return kPrintReg2S;
998 case kFormat2D:
999 return kPrintReg2D;
1000 case kFormat1D:
1001 return kPrintReg1D;
1002
1003 case kFormatB:
1004 return kPrintReg1B;
1005 case kFormatH:
1006 return kPrintReg1H;
1007 case kFormatS:
1008 return kPrintReg1S;
1009 case kFormatD:
1010 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +01001011
1012 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001013 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +01001014 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001015 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +01001016 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001017 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +01001018 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001019 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001020 }
1021}
1022
1023
1024Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1025 VectorFormat vform) {
1026 switch (vform) {
1027 default:
1028 VIXL_UNREACHABLE();
1029 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001030 case kFormat8H:
1031 return kPrintReg8HFP;
1032 case kFormat4H:
1033 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001034 case kFormat4S:
1035 return kPrintReg4SFP;
1036 case kFormat2S:
1037 return kPrintReg2SFP;
1038 case kFormat2D:
1039 return kPrintReg2DFP;
1040 case kFormat1D:
1041 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001042 case kFormatH:
1043 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001044 case kFormatS:
1045 return kPrintReg1SFP;
1046 case kFormatD:
1047 return kPrintReg1DFP;
1048 }
1049}
1050
Jacob Bramley423e5422019-11-13 19:15:55 +00001051void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001052 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +00001053 if (i == kSpRegCode) i = kSPRegInternalCode;
1054 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001055 }
1056}
1057
Jacob Bramley423e5422019-11-13 19:15:55 +00001058void Simulator::PrintVRegisters() {
1059 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1060 PrintVRegister(i);
1061 }
1062}
1063
1064void Simulator::PrintZRegisters() {
1065 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
1066 PrintZRegister(i);
1067 }
1068}
1069
1070void Simulator::PrintWrittenRegisters() {
1071 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1072 if (registers_[i].WrittenSinceLastLog()) {
1073 if (i == kSpRegCode) i = kSPRegInternalCode;
1074 PrintRegister(i);
1075 }
1076 }
1077}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001078
1079void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001080 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001081 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001082 if (vregisters_[i].WrittenSinceLastLog()) {
1083 // Z registers are initialised in the constructor before the user can
1084 // configure the CPU features, so we must also check for SVE here.
1085 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
1086 PrintZRegister(i);
1087 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00001088 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +01001089 }
1090 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001091 }
1092}
1093
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001094void Simulator::PrintWrittenPRegisters() {
1095 // P registers are initialised in the constructor before the user can
1096 // configure the CPU features, so we must check for SVE here.
1097 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
1098 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
1099 if (pregisters_[i].WrittenSinceLastLog()) {
1100 PrintPRegister(i);
1101 }
1102 }
Jacob Bramley0d754e92020-06-18 10:59:09 +01001103 if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001104}
1105
Alexandre Ramesd3832962016-07-04 15:03:43 +01001106void Simulator::PrintSystemRegisters() {
1107 PrintSystemRegister(NZCV);
1108 PrintSystemRegister(FPCR);
1109}
1110
Jacob Bramley423e5422019-11-13 19:15:55 +00001111void Simulator::PrintRegisterValue(const uint8_t* value,
1112 int value_size,
1113 PrintRegisterFormat format) {
1114 int print_width = GetPrintRegSizeInBytes(format);
1115 VIXL_ASSERT(print_width <= value_size);
1116 for (int i = value_size - 1; i >= print_width; i--) {
1117 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +01001118 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +00001119 // If we aren't explicitly printing a partial value, ensure that the
1120 // unprinted bits are zero.
1121 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001122 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001123 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +00001124 for (int i = print_width - 1; i >= 0; i--) {
1125 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001126 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001127}
1128
Jacob Bramley423e5422019-11-13 19:15:55 +00001129void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
1130 uint16_t lane_mask,
1131 PrintRegisterFormat format) {
1132 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
1133 int lane_size = GetPrintRegLaneSizeInBytes(format);
1134 fprintf(stream_, " (");
1135 bool last_inactive = false;
1136 const char* sep = "";
1137 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
1138 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
1139 if (access) {
1140 // Read the lane as a double, so we can format all FP types in the same
1141 // way. We squash NaNs, and a double can exactly represent any other value
1142 // that the smaller types can represent, so this is lossless.
1143 double element;
1144 switch (lane_size) {
1145 case kHRegSizeInBytes: {
1146 Float16 element_fp16;
1147 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
1148 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
1149 element = FPToDouble(element_fp16, kUseDefaultNaN);
1150 break;
1151 }
1152 case kSRegSizeInBytes: {
1153 float element_fp32;
1154 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
1155 element = static_cast<double>(element_fp32);
1156 break;
1157 }
1158 case kDRegSizeInBytes: {
1159 memcpy(&element, &value[i * lane_size], sizeof(element));
1160 break;
1161 }
1162 default:
1163 VIXL_UNREACHABLE();
1164 fprintf(stream_, "{UnknownFPValue}");
1165 continue;
1166 }
1167 if (IsNaN(element)) {
1168 // The fprintf behaviour for NaNs is implementation-defined. Always
1169 // print "nan", so that traces are consistent.
1170 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
1171 } else {
1172 fprintf(stream_,
1173 "%s%s%#.4g%s",
1174 sep,
1175 clr_vreg_value,
1176 element,
1177 clr_normal);
1178 }
1179 last_inactive = false;
1180 } else if (!last_inactive) {
1181 // Replace each contiguous sequence of inactive lanes with "...".
1182 fprintf(stream_, "%s...", sep);
1183 last_inactive = true;
1184 }
1185 }
1186 fprintf(stream_, ")");
1187}
1188
1189void Simulator::PrintRegister(int code,
1190 PrintRegisterFormat format,
1191 const char* suffix) {
1192 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
1193 (static_cast<unsigned>(code) == kSPRegInternalCode));
1194 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
1195 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
1196
1197 SimRegister* reg;
1198 SimRegister zero;
1199 if (code == kZeroRegCode) {
1200 reg = &zero;
1201 } else {
1202 // registers_[31] holds the SP.
1203 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1204 reg = &registers_[code % kNumberOfRegisters];
1205 }
1206
1207 // We trace register writes as whole register values, implying that any
1208 // unprinted bits are all zero:
1209 // "# x{code}: 0x{-----value----}"
1210 // "# w{code}: 0x{-value}"
1211 // Stores trace partial register values, implying nothing about the unprinted
1212 // bits:
1213 // "# x{code}<63:0>: 0x{-----value----}"
1214 // "# x{code}<31:0>: 0x{-value}"
1215 // "# x{code}<15:0>: 0x{--}"
1216 // "# x{code}<7:0>: 0x{}"
1217
1218 bool is_partial = (format & kPrintRegPartial) != 0;
1219 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1220 std::stringstream name;
1221 if (is_partial) {
1222 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
1223 } else {
1224 // Notify the register that it has been logged, but only if we're printing
1225 // all of it.
1226 reg->NotifyRegisterLogged();
1227 switch (print_reg_size) {
1228 case kWRegSize:
1229 name << WRegNameForCode(code);
1230 break;
1231 case kXRegSize:
1232 name << XRegNameForCode(code);
1233 break;
1234 default:
1235 VIXL_UNREACHABLE();
1236 return;
1237 }
1238 }
1239
1240 fprintf(stream_,
1241 "# %s%*s: %s",
1242 clr_reg_name,
1243 kPrintRegisterNameFieldWidth,
1244 name.str().c_str(),
1245 clr_reg_value);
1246 PrintRegisterValue(*reg, format);
1247 fprintf(stream_, "%s%s", clr_normal, suffix);
1248}
1249
1250void Simulator::PrintVRegister(int code,
1251 PrintRegisterFormat format,
1252 const char* suffix) {
1253 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
1254 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
1255 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
1256 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
1257
1258 // We trace register writes as whole register values, implying that any
1259 // unprinted bits are all zero:
1260 // "# v{code}: 0x{-------------value------------}"
1261 // "# d{code}: 0x{-----value----}"
1262 // "# s{code}: 0x{-value}"
1263 // "# h{code}: 0x{--}"
1264 // "# b{code}: 0x{}"
1265 // Stores trace partial register values, implying nothing about the unprinted
1266 // bits:
1267 // "# v{code}<127:0>: 0x{-------------value------------}"
1268 // "# v{code}<63:0>: 0x{-----value----}"
1269 // "# v{code}<31:0>: 0x{-value}"
1270 // "# v{code}<15:0>: 0x{--}"
1271 // "# v{code}<7:0>: 0x{}"
1272
1273 bool is_partial = ((format & kPrintRegPartial) != 0);
1274 std::stringstream name;
1275 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1276 if (is_partial) {
1277 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1278 } else {
1279 // Notify the register that it has been logged, but only if we're printing
1280 // all of it.
1281 vregisters_[code].NotifyRegisterLogged();
1282 switch (print_reg_size) {
1283 case kBRegSize:
1284 name << BRegNameForCode(code);
1285 break;
1286 case kHRegSize:
1287 name << HRegNameForCode(code);
1288 break;
1289 case kSRegSize:
1290 name << SRegNameForCode(code);
1291 break;
1292 case kDRegSize:
1293 name << DRegNameForCode(code);
1294 break;
1295 case kQRegSize:
1296 name << VRegNameForCode(code);
1297 break;
1298 default:
1299 VIXL_UNREACHABLE();
1300 return;
1301 }
1302 }
1303
1304 fprintf(stream_,
1305 "# %s%*s: %s",
1306 clr_vreg_name,
1307 kPrintRegisterNameFieldWidth,
1308 name.str().c_str(),
1309 clr_vreg_value);
1310 PrintRegisterValue(vregisters_[code], format);
1311 fprintf(stream_, "%s", clr_normal);
1312 if ((format & kPrintRegAsFP) != 0) {
1313 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1314 }
1315 fprintf(stream_, "%s", suffix);
1316}
1317
1318void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1319 int reg_count,
1320 uint16_t focus_mask,
1321 PrintRegisterFormat format) {
1322 bool print_fp = (format & kPrintRegAsFP) != 0;
1323 // Suppress FP formatting, so we can specify the lanes we're interested in.
1324 PrintRegisterFormat format_no_fp =
1325 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1326
1327 for (int r = 0; r < reg_count; r++) {
1328 int code = (rt_code + r) % kNumberOfVRegisters;
1329 PrintVRegister(code, format_no_fp, "");
1330 if (print_fp) {
1331 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1332 }
1333 fprintf(stream_, "\n");
1334 }
1335}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001336
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001337void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1338 int q_index,
1339 int reg_count,
1340 uint16_t focus_mask,
1341 PrintRegisterFormat format) {
1342 bool print_fp = (format & kPrintRegAsFP) != 0;
1343 // Suppress FP formatting, so we can specify the lanes we're interested in.
1344 PrintRegisterFormat format_no_fp =
1345 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001346
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001347 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001348
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001349 const unsigned size = kQRegSizeInBytes;
1350 unsigned byte_index = q_index * size;
1351 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1352 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001353
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001354 for (int r = 0; r < reg_count; r++) {
1355 int code = (rt_code + r) % kNumberOfZRegisters;
1356 PrintPartialZRegister(code, q_index, format_no_fp, "");
1357 if (print_fp) {
1358 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001359 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001360 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001361 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001362}
1363
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001364void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1365 // We're going to print the register in parts, so force a partial format.
1366 format = GetPrintRegPartial(format);
1367 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1368 int vl = GetVectorLengthInBits();
1369 VIXL_ASSERT((vl % kQRegSize) == 0);
1370 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1371 PrintPartialZRegister(code, i, format);
1372 }
1373 vregisters_[code].NotifyRegisterLogged();
1374}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001375
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001376void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1377 // We're going to print the register in parts, so force a partial format.
1378 format = GetPrintRegPartial(format);
1379 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1380 int vl = GetVectorLengthInBits();
1381 VIXL_ASSERT((vl % kQRegSize) == 0);
1382 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1383 PrintPartialPRegister(code, i, format);
1384 }
1385 pregisters_[code].NotifyRegisterLogged();
1386}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001387
Jacob Bramley0d754e92020-06-18 10:59:09 +01001388void Simulator::PrintFFR(PrintRegisterFormat format) {
1389 // We're going to print the register in parts, so force a partial format.
1390 format = GetPrintRegPartial(format);
1391 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1392 int vl = GetVectorLengthInBits();
1393 VIXL_ASSERT((vl % kQRegSize) == 0);
1394 SimPRegister& ffr = ReadFFR();
1395 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1396 PrintPartialPRegister("FFR", ffr, i, format);
1397 }
1398 ffr.NotifyRegisterLogged();
1399}
1400
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001401void Simulator::PrintPartialZRegister(int code,
1402 int q_index,
1403 PrintRegisterFormat format,
1404 const char* suffix) {
1405 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1406 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1407 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1408 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001409
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001410 // We _only_ trace partial Z register values in Q-sized chunks, because
1411 // they're often too large to reasonably fit on a single line. Each line
1412 // implies nothing about the unprinted bits.
1413 // "# z{code}<127:0>: 0x{-------------value------------}"
1414
1415 format = GetPrintRegAsQChunkOfSVE(format);
1416
1417 const unsigned size = kQRegSizeInBytes;
1418 unsigned byte_index = q_index * size;
1419 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1420 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1421
1422 int lsb = q_index * kQRegSize;
1423 int msb = lsb + kQRegSize - 1;
1424 std::stringstream name;
1425 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001426
1427 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001428 "# %s%*s: %s",
1429 clr_vreg_name,
1430 kPrintRegisterNameFieldWidth,
1431 name.str().c_str(),
1432 clr_vreg_value);
1433 PrintRegisterValue(value, size, format);
1434 fprintf(stream_, "%s", clr_normal);
1435 if ((format & kPrintRegAsFP) != 0) {
1436 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1437 }
1438 fprintf(stream_, "%s", suffix);
1439}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001440
Jacob Bramley0d754e92020-06-18 10:59:09 +01001441void Simulator::PrintPartialPRegister(const char* name,
1442 const SimPRegister& reg,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001443 int q_index,
1444 PrintRegisterFormat format,
1445 const char* suffix) {
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001446 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1447 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1448 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1449
1450 // We don't currently use the format for anything here.
1451 USE(format);
1452
1453 // We _only_ trace partial P register values, because they're often too large
1454 // to reasonably fit on a single line. Each line implies nothing about the
1455 // unprinted bits.
1456 //
1457 // We print values in binary, with spaces between each bit, in order for the
1458 // bits to align with the Z register bytes that they predicate.
Jacob Bramley0d754e92020-06-18 10:59:09 +01001459 // "# {name}<15:0>: 0b{-------------value------------}"
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001460
1461 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1462 int lsb = q_index * print_size_in_bits;
1463 int msb = lsb + print_size_in_bits - 1;
Jacob Bramley0d754e92020-06-18 10:59:09 +01001464 std::stringstream prefix;
1465 prefix << name << '<' << msb << ':' << lsb << '>';
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001466
1467 fprintf(stream_,
1468 "# %s%*s: %s0b",
1469 clr_preg_name,
1470 kPrintRegisterNameFieldWidth,
Jacob Bramley0d754e92020-06-18 10:59:09 +01001471 prefix.str().c_str(),
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001472 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001473 for (int i = msb; i >= lsb; i--) {
Jacob Bramley0d754e92020-06-18 10:59:09 +01001474 fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001475 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001476 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001477}
1478
Jacob Bramley0d754e92020-06-18 10:59:09 +01001479void Simulator::PrintPartialPRegister(int code,
1480 int q_index,
1481 PrintRegisterFormat format,
1482 const char* suffix) {
1483 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1484 PrintPartialPRegister(PRegNameForCode(code),
1485 pregisters_[code],
1486 q_index,
1487 format,
1488 suffix);
1489}
1490
Alexandre Ramesd3832962016-07-04 15:03:43 +01001491void Simulator::PrintSystemRegister(SystemRegister id) {
1492 switch (id) {
1493 case NZCV:
1494 fprintf(stream_,
1495 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1496 clr_flag_name,
1497 clr_flag_value,
1498 ReadNzcv().GetN(),
1499 ReadNzcv().GetZ(),
1500 ReadNzcv().GetC(),
1501 ReadNzcv().GetV(),
1502 clr_normal);
1503 break;
1504 case FPCR: {
1505 static const char* rmode[] = {"0b00 (Round to Nearest)",
1506 "0b01 (Round towards Plus Infinity)",
1507 "0b10 (Round towards Minus Infinity)",
1508 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001509 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001510 fprintf(stream_,
1511 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1512 clr_flag_name,
1513 clr_flag_value,
1514 ReadFpcr().GetAHP(),
1515 ReadFpcr().GetDN(),
1516 ReadFpcr().GetFZ(),
1517 rmode[ReadFpcr().GetRMode()],
1518 clr_normal);
1519 break;
1520 }
1521 default:
1522 VIXL_UNREACHABLE();
1523 }
1524}
1525
Jacob Bramley423e5422019-11-13 19:15:55 +00001526uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1527 uint16_t future_access_mask,
1528 int struct_element_count,
1529 int lane_size_in_bytes,
1530 const char* op,
1531 uintptr_t address,
1532 int reg_size_in_bytes) {
1533 // We want to assume that we'll access at least one lane.
1534 VIXL_ASSERT(access_mask != 0);
1535 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1536 (reg_size_in_bytes == kQRegSizeInBytes));
1537 bool started_annotation = false;
1538 // Indent to match the register field, the fixed formatting, and the value
1539 // prefix ("0x"): "# {name}: 0x"
1540 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1541 // First, annotate the lanes (byte by byte).
1542 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1543 bool access = (access_mask & (1 << lane)) != 0;
1544 bool future = (future_access_mask & (1 << lane)) != 0;
1545 if (started_annotation) {
1546 // If we've started an annotation, draw a horizontal line in addition to
1547 // any other symbols.
1548 if (access) {
1549 fprintf(stream_, "─╨");
1550 } else if (future) {
1551 fprintf(stream_, "─║");
1552 } else {
1553 fprintf(stream_, "──");
1554 }
1555 } else {
1556 if (access) {
1557 started_annotation = true;
1558 fprintf(stream_, " â•™");
1559 } else if (future) {
1560 fprintf(stream_, " â•‘");
1561 } else {
1562 fprintf(stream_, " ");
1563 }
1564 }
1565 }
1566 VIXL_ASSERT(started_annotation);
1567 fprintf(stream_, "─ 0x");
1568 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1569 // Print the most-significant struct element first.
1570 const char* sep = "";
1571 for (int i = struct_element_count - 1; i >= 0; i--) {
1572 int offset = lane_size_in_bytes * i;
1573 uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset);
1574 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1575 sep = "'";
1576 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001577 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001578 " %s %s0x%016" PRIxPTR "%s\n",
1579 op,
1580 clr_memory_address,
1581 address,
1582 clr_normal);
1583 return future_access_mask & ~access_mask;
1584}
1585
1586void Simulator::PrintAccess(int code,
1587 PrintRegisterFormat format,
1588 const char* op,
1589 uintptr_t address) {
1590 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1591 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1592 if ((format & kPrintRegPartial) == 0) {
1593 registers_[code].NotifyRegisterLogged();
1594 }
1595 // Scalar-format accesses use a simple format:
1596 // "# {reg}: 0x{value} -> {address}"
1597
1598 // Suppress the newline, so the access annotation goes on the same line.
1599 PrintRegister(code, format, "");
1600 fprintf(stream_,
1601 " %s %s0x%016" PRIxPTR "%s\n",
1602 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001603 clr_memory_address,
1604 address,
1605 clr_normal);
1606}
1607
Jacob Bramley423e5422019-11-13 19:15:55 +00001608void Simulator::PrintVAccess(int code,
1609 PrintRegisterFormat format,
1610 const char* op,
1611 uintptr_t address) {
1612 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001613
Jacob Bramley423e5422019-11-13 19:15:55 +00001614 // Scalar-format accesses use a simple format:
1615 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001616
Jacob Bramley423e5422019-11-13 19:15:55 +00001617 // Suppress the newline, so the access annotation goes on the same line.
1618 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001619 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001620 " %s %s0x%016" PRIxPTR "%s\n",
1621 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001622 clr_memory_address,
1623 address,
1624 clr_normal);
1625}
1626
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001627void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001628 int reg_count,
1629 PrintRegisterFormat format,
1630 const char* op,
1631 uintptr_t address) {
1632 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1633
1634 // For example:
1635 // "# v{code}: 0x{value}"
1636 // "# ...: 0x{value}"
1637 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1638 // "# ╙───── {struct_value} -> {highest_address}"
1639
1640 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001641 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001642
1643 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1644 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1645 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1646 uint16_t access_mask = 1 << i;
1647 VIXL_ASSERT((lane_mask & access_mask) != 0);
1648 lane_mask = PrintPartialAccess(access_mask,
1649 lane_mask,
1650 reg_count,
1651 lane_size_in_bytes,
1652 op,
1653 address + (i * reg_count));
1654 }
1655}
1656
1657void Simulator::PrintVSingleStructAccess(int rt_code,
1658 int reg_count,
1659 int lane,
1660 PrintRegisterFormat format,
1661 const char* op,
1662 uintptr_t address) {
1663 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1664
1665 // For example:
1666 // "# v{code}: 0x{value}"
1667 // "# ...: 0x{value}"
1668 // "# ╙───── {struct_value} -> {address}"
1669
1670 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1671 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1672 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1673 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1674}
1675
1676void Simulator::PrintVReplicatingStructAccess(int rt_code,
1677 int reg_count,
1678 PrintRegisterFormat format,
1679 const char* op,
1680 uintptr_t address) {
1681 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1682
1683 // For example:
1684 // "# v{code}: 0x{value}"
1685 // "# ...: 0x{value}"
1686 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1687
1688 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1689 uint16_t lane_mask = GetPrintRegLaneMask(format);
1690 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1691 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1692}
1693
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001694void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1695 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1696
1697 // Scalar-format accesses are split into separate chunks, each of which uses a
1698 // simple format:
1699 // "# z{code}<127:0>: 0x{value} -> {address}"
1700 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1701 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1702 // etc
1703
1704 int vl = GetVectorLengthInBits();
1705 VIXL_ASSERT((vl % kQRegSize) == 0);
1706 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1707 // Suppress the newline, so the access annotation goes on the same line.
1708 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1709 fprintf(stream_,
1710 " %s %s0x%016" PRIxPTR "%s\n",
1711 op,
1712 clr_memory_address,
1713 address,
1714 clr_normal);
1715 address += kQRegSizeInBytes;
1716 }
1717}
1718
1719void Simulator::PrintZStructAccess(int rt_code,
1720 int reg_count,
1721 const LogicPRegister& pg,
1722 PrintRegisterFormat format,
1723 int msize_in_bytes,
1724 const char* op,
1725 const LogicSVEAddressVector& addr) {
1726 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1727
1728 // For example:
1729 // "# z{code}<255:128>: 0x{value}"
1730 // "# ...<255:128>: 0x{value}"
1731 // "# ║ ╙─ {struct_value} -> {first_address}"
1732 // "# ╙───── {struct_value} -> {last_address}"
1733
1734 // We're going to print the register in parts, so force a partial format.
1735 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1736 format = GetPrintRegPartial(format);
1737
1738 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1739 int vl = GetVectorLengthInBits();
1740 VIXL_ASSERT((vl % kQRegSize) == 0);
1741 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1742 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1743 uint16_t pred =
1744 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1745 if ((pred == 0) && skip_inactive_chunks) continue;
1746
1747 PrintZRegistersForStructuredAccess(rt_code,
1748 q_index,
1749 reg_count,
1750 pred,
1751 format);
1752 if (pred == 0) {
1753 // This register chunk has no active lanes. The loop below would print
1754 // nothing, so leave a blank line to keep structures grouped together.
1755 fprintf(stream_, "#\n");
1756 continue;
1757 }
1758 for (int i = 0; i < lanes_per_q; i++) {
1759 uint16_t access = 1 << (i * esize_in_bytes);
1760 int lane = (q_index * lanes_per_q) + i;
1761 // Skip inactive lanes.
1762 if ((pred & access) == 0) continue;
1763 pred = PrintPartialAccess(access,
1764 pred,
1765 reg_count,
1766 msize_in_bytes,
1767 op,
1768 addr.GetStructAddress(lane));
1769 }
1770 }
1771
1772 // We print the whole register, even for stores.
1773 for (int i = 0; i < reg_count; i++) {
1774 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1775 }
1776}
1777
1778void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1779 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1780
1781 // Scalar-format accesses are split into separate chunks, each of which uses a
1782 // simple format:
1783 // "# p{code}<15:0>: 0b{value} -> {address}"
1784 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1785 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1786 // etc
1787
1788 int vl = GetVectorLengthInBits();
1789 VIXL_ASSERT((vl % kQRegSize) == 0);
1790 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1791 // Suppress the newline, so the access annotation goes on the same line.
1792 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1793 fprintf(stream_,
1794 " %s %s0x%016" PRIxPTR "%s\n",
1795 op,
1796 clr_memory_address,
1797 address,
1798 clr_normal);
1799 address += kQRegSizeInBytes;
1800 }
1801}
1802
Jacob Bramley423e5422019-11-13 19:15:55 +00001803void Simulator::PrintRead(int rt_code,
1804 PrintRegisterFormat format,
1805 uintptr_t address) {
1806 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1807 registers_[rt_code].NotifyRegisterLogged();
1808 PrintAccess(rt_code, format, "<-", address);
1809}
1810
1811void Simulator::PrintExtendingRead(int rt_code,
1812 PrintRegisterFormat format,
1813 int access_size_in_bytes,
1814 uintptr_t address) {
1815 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1816 if (access_size_in_bytes == reg_size_in_bytes) {
1817 // There is no extension here, so print a simple load.
1818 PrintRead(rt_code, format, address);
1819 return;
1820 }
1821 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1822
1823 // For sign- and zero-extension, make it clear that the resulting register
1824 // value is different from what is loaded from memory.
1825 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1826 registers_[rt_code].NotifyRegisterLogged();
1827 PrintRegister(rt_code, format);
1828 PrintPartialAccess(1,
1829 0,
1830 1,
1831 access_size_in_bytes,
1832 "<-",
1833 address,
1834 kXRegSizeInBytes);
1835}
1836
1837void Simulator::PrintVRead(int rt_code,
1838 PrintRegisterFormat format,
1839 uintptr_t address) {
1840 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1841 vregisters_[rt_code].NotifyRegisterLogged();
1842 PrintVAccess(rt_code, format, "<-", address);
1843}
1844
Jacob Bramley423e5422019-11-13 19:15:55 +00001845void Simulator::PrintWrite(int rt_code,
1846 PrintRegisterFormat format,
1847 uintptr_t address) {
1848 // Because this trace doesn't represent a change to the source register's
1849 // value, only print the relevant part of the value.
1850 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001851 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001852 registers_[rt_code].NotifyRegisterLogged();
1853 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001854}
1855
Jacob Bramley423e5422019-11-13 19:15:55 +00001856void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001857 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001858 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001859 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001860 // value, only print the relevant part of the value.
1861 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001862 // It only makes sense to write scalar values here. Vectors are handled by
1863 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001864 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001865 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001866}
1867
Jacob Bramleye79723a2016-06-07 17:50:47 +01001868void Simulator::PrintTakenBranch(const Instruction* target) {
1869 fprintf(stream_,
1870 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1871 clr_branch_marker,
1872 clr_normal,
1873 reinterpret_cast<uint64_t>(target));
1874}
1875
Alexandre Ramesd3832962016-07-04 15:03:43 +01001876// Visitors---------------------------------------------------------------------
1877
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001878
Martyn Capewell8c691852020-07-15 18:33:15 +01001879void Simulator::Visit(Metadata* metadata, const Instruction* instr) {
1880 VIXL_ASSERT(metadata->count("form") > 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001881 std::string form = (*metadata)["form"];
Martyn Capewell8c691852020-07-15 18:33:15 +01001882 if ((form_to_visitor_.count(form) > 0) && form_to_visitor_[form]) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01001883 form_hash_ = Hash(form.c_str());
Martyn Capewell8c691852020-07-15 18:33:15 +01001884 form_to_visitor_[form](this, instr);
1885 } else {
1886 VisitUnimplemented(instr);
1887 }
1888}
1889
Martyn Capewell6bf28752020-08-05 11:57:06 +01001890void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell51643312020-08-24 15:58:57 +01001891 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01001892 SimPRegister& pd = ReadPRegister(instr->GetPd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001893 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001894 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001895 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001896
1897 switch (form_hash_) {
1898 case Hash("match_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001899 match(vform, pd, zn, zm, /* negate_match = */ false);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001900 break;
1901 case Hash("nmatch_p_p_zz"):
Martyn Capewell51643312020-08-24 15:58:57 +01001902 match(vform, pd, zn, zm, /* negate_match = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001903 break;
1904 default:
1905 VIXL_UNIMPLEMENTED();
1906 }
Martyn Capewell51643312020-08-24 15:58:57 +01001907 mov_zeroing(pd, pg, pd);
1908 PredTest(vform, pg, pd);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001909}
1910
Martyn Capewell6bf28752020-08-05 11:57:06 +01001911void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {
Martyn Capewell35636df2020-10-15 15:14:12 +01001912 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01001913 SimPRegister& pd = ReadPRegister(instr->GetPd());
Martyn Capewell35636df2020-10-15 15:14:12 +01001914 uint64_t src1 = ReadXRegister(instr->GetRn());
1915 uint64_t src2 = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001916
Martyn Capewell35636df2020-10-15 15:14:12 +01001917 uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1);
1918 absdiff >>= LaneSizeInBytesLog2FromFormat(vform);
1919
1920 bool no_conflict = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01001921 switch (form_hash_) {
1922 case Hash("whilerw_p_rr"):
Martyn Capewell35636df2020-10-15 15:14:12 +01001923 no_conflict = (absdiff == 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001924 break;
1925 case Hash("whilewr_p_rr"):
Martyn Capewell35636df2020-10-15 15:14:12 +01001926 no_conflict = (absdiff == 0) || (src2 <= src1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001927 break;
1928 default:
1929 VIXL_UNIMPLEMENTED();
1930 }
Martyn Capewell35636df2020-10-15 15:14:12 +01001931
1932 LogicPRegister dst(pd);
1933 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1934 dst.SetActive(vform,
1935 i,
1936 no_conflict || (static_cast<uint64_t>(i) < absdiff));
1937 }
1938
1939 PredTest(vform, GetPTrue(), pd);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001940}
1941
1942void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
1943 SimVRegister& zd = ReadVRegister(instr->GetRd());
1944 USE(zd);
1945 SimVRegister& zn1 = ReadVRegister(instr->GetRn());
1946 USE(zn1);
1947
1948 switch (form_hash_) {
1949 case Hash("ext_z_zi_con"):
1950 VIXL_UNIMPLEMENTED();
1951 break;
1952 default:
1953 VIXL_UNIMPLEMENTED();
1954 }
1955}
1956
1957void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
1958 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001959 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001960 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01001961
1962 switch (form_hash_) {
1963 case Hash("histseg_z_zz"):
Martyn Capewell710ec6f2020-10-22 16:56:17 +01001964 if (instr->GetSVEVectorFormat() == kFormatVnB) {
1965 histogram(kFormatVnB,
1966 zd,
1967 GetPTrue(),
1968 zn,
1969 zm,
1970 /* do_segmented = */ true);
1971 } else {
1972 VIXL_UNIMPLEMENTED();
1973 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01001974 break;
1975 case Hash("pmul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07001976 pmul(kFormatVnB, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01001977 break;
1978 default:
1979 VIXL_UNIMPLEMENTED();
1980 }
1981}
1982
1983void Simulator::Simulate_ZdD_PgM_ZnS(const Instruction* instr) {
1984 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
1985 USE(pg);
1986 SimVRegister& zd = ReadVRegister(instr->GetRd());
1987 USE(zd);
1988 SimVRegister& zn = ReadVRegister(instr->GetRn());
1989 USE(zn);
1990
1991 switch (form_hash_) {
1992 case Hash("fcvtlt_z_p_z_s2d"):
1993 VIXL_UNIMPLEMENTED();
1994 break;
1995 default:
1996 VIXL_UNIMPLEMENTED();
1997 }
1998}
1999
Martyn Capewellf272b9c2020-11-05 18:30:16 +00002000void Simulator::SimulateSVEMulIndex(const Instruction* instr) {
2001 VectorFormat vform = instr->GetSVEVectorFormat();
2002 SimVRegister& zd = ReadVRegister(instr->GetRd());
2003 SimVRegister& zn = ReadVRegister(instr->GetRn());
2004
2005 // The encoding for B and H-sized lanes are redefined to encode the most
2006 // significant bit of index for H-sized lanes. B-sized lanes are not
2007 // supported.
2008 if (vform == kFormatVnB) vform = kFormatVnH;
2009
2010 VIXL_ASSERT((form_hash_ == Hash("mul_z_zzi_d")) ||
2011 (form_hash_ == Hash("mul_z_zzi_h")) ||
2012 (form_hash_ == Hash("mul_z_zzi_s")));
2013
2014 SimVRegister temp;
2015 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2016 mul(vform, zd, zn, temp);
2017}
2018
Martyn Capewell8f4e1692020-11-06 14:16:14 +00002019void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) {
2020 VectorFormat vform = instr->GetSVEVectorFormat();
2021 SimVRegister& zda = ReadVRegister(instr->GetRd());
2022 SimVRegister& zn = ReadVRegister(instr->GetRn());
2023
2024 // The encoding for B and H-sized lanes are redefined to encode the most
2025 // significant bit of index for H-sized lanes. B-sized lanes are not
2026 // supported.
2027 if (vform == kFormatVnB) vform = kFormatVnH;
2028
2029 VIXL_ASSERT((form_hash_ == Hash("mla_z_zzzi_d")) ||
2030 (form_hash_ == Hash("mla_z_zzzi_h")) ||
2031 (form_hash_ == Hash("mla_z_zzzi_s")) ||
2032 (form_hash_ == Hash("mls_z_zzzi_d")) ||
2033 (form_hash_ == Hash("mls_z_zzzi_h")) ||
2034 (form_hash_ == Hash("mls_z_zzzi_s")));
2035
2036 SimVRegister temp;
2037 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2038 if (instr->ExtractBit(10) == 0) {
2039 mla(vform, zda, zda, zn, temp);
2040 } else {
2041 mls(vform, zda, zda, zn, temp);
2042 }
2043}
2044
Martyn Capewell6bf28752020-08-05 11:57:06 +01002045void Simulator::Simulate_ZdD_ZnD_ZmD_imm(const Instruction* instr) {
2046 SimVRegister& zd = ReadVRegister(instr->GetRd());
2047 USE(zd);
2048 SimVRegister& zn = ReadVRegister(instr->GetRn());
2049 USE(zn);
2050
2051 switch (form_hash_) {
2052 case Hash("mul_z_zzi_d"):
2053 VIXL_UNIMPLEMENTED();
2054 break;
2055 case Hash("sqdmulh_z_zzi_d"):
2056 VIXL_UNIMPLEMENTED();
2057 break;
2058 case Hash("sqrdmulh_z_zzi_d"):
2059 VIXL_UNIMPLEMENTED();
2060 break;
2061 default:
2062 VIXL_UNIMPLEMENTED();
2063 }
2064}
2065
TatWai Chong1719b712020-09-25 18:16:40 -07002066void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002067 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002068 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002069 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong1719b712020-09-25 18:16:40 -07002070
2071 SimVRegister temp, zm_idx, zn_b, zn_t;
2072 // Instead of calling the indexed form of the instruction logic, we call the
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002073 // vector form, which can reuse existing function logic without modification.
Martyn Capewell97ca8062020-10-23 14:45:14 +01002074 // Select the specified elements based on the index input and than pack them
2075 // to the corresponding position.
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002076 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2077 dup_elements_to_segments(vform_half, temp, instr->GetSVEMulLongZmAndIndex());
2078 pack_even_elements(vform_half, zm_idx, temp);
2079
2080 pack_even_elements(vform_half, zn_b, zn);
2081 pack_odd_elements(vform_half, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002082
2083 switch (form_hash_) {
Martyn Capewell573246c2021-01-07 17:24:00 +00002084 case Hash("smullb_z_zzi_s"):
Martyn Capewell6bf28752020-08-05 11:57:06 +01002085 case Hash("smullb_z_zzi_d"):
Martyn Capewell573246c2021-01-07 17:24:00 +00002086 smull(vform, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002087 break;
Martyn Capewell573246c2021-01-07 17:24:00 +00002088 case Hash("smullt_z_zzi_s"):
Martyn Capewell6bf28752020-08-05 11:57:06 +01002089 case Hash("smullt_z_zzi_d"):
Martyn Capewell573246c2021-01-07 17:24:00 +00002090 smull(vform, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002091 break;
2092 case Hash("sqdmullb_z_zzi_d"):
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002093 sqdmull(vform, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002094 break;
2095 case Hash("sqdmullt_z_zzi_d"):
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002096 sqdmull(vform, zd, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002097 break;
Martyn Capewell573246c2021-01-07 17:24:00 +00002098 case Hash("umullb_z_zzi_s"):
Martyn Capewell6bf28752020-08-05 11:57:06 +01002099 case Hash("umullb_z_zzi_d"):
Martyn Capewell573246c2021-01-07 17:24:00 +00002100 umull(vform, zd, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002101 break;
Martyn Capewell573246c2021-01-07 17:24:00 +00002102 case Hash("umullt_z_zzi_s"):
Martyn Capewell6bf28752020-08-05 11:57:06 +01002103 case Hash("umullt_z_zzi_d"):
Martyn Capewell573246c2021-01-07 17:24:00 +00002104 umull(vform, zd, zn_t, zm_idx);
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002105 break;
2106 case Hash("sqdmullb_z_zzi_s"):
2107 sqdmull(vform, zd, zn_b, zm_idx);
2108 break;
2109 case Hash("sqdmullt_z_zzi_s"):
2110 sqdmull(vform, zd, zn_t, zm_idx);
2111 break;
Martyn Capewell2e66dc72020-12-02 17:59:09 +00002112 case Hash("smlalb_z_zzzi_s"):
2113 case Hash("smlalb_z_zzzi_d"):
2114 smlal(vform, zd, zn_b, zm_idx);
2115 break;
2116 case Hash("smlalt_z_zzzi_s"):
2117 case Hash("smlalt_z_zzzi_d"):
2118 smlal(vform, zd, zn_t, zm_idx);
2119 break;
2120 case Hash("smlslb_z_zzzi_s"):
2121 case Hash("smlslb_z_zzzi_d"):
2122 smlsl(vform, zd, zn_b, zm_idx);
2123 break;
2124 case Hash("smlslt_z_zzzi_s"):
2125 case Hash("smlslt_z_zzzi_d"):
2126 smlsl(vform, zd, zn_t, zm_idx);
2127 break;
2128 case Hash("umlalb_z_zzzi_s"):
2129 case Hash("umlalb_z_zzzi_d"):
2130 umlal(vform, zd, zn_b, zm_idx);
2131 break;
2132 case Hash("umlalt_z_zzzi_s"):
2133 case Hash("umlalt_z_zzzi_d"):
2134 umlal(vform, zd, zn_t, zm_idx);
2135 break;
2136 case Hash("umlslb_z_zzzi_s"):
2137 case Hash("umlslb_z_zzzi_d"):
2138 umlsl(vform, zd, zn_b, zm_idx);
2139 break;
2140 case Hash("umlslt_z_zzzi_s"):
2141 case Hash("umlslt_z_zzzi_d"):
2142 umlsl(vform, zd, zn_t, zm_idx);
2143 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002144 default:
2145 VIXL_UNIMPLEMENTED();
2146 }
2147}
2148
2149void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2150 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2151 USE(pg);
2152 SimVRegister& zd = ReadVRegister(instr->GetRd());
2153 USE(zd);
2154 SimVRegister& zn = ReadVRegister(instr->GetRn());
2155 USE(zn);
2156
2157 switch (form_hash_) {
2158 case Hash("fcvtnt_z_p_z_s2h"):
2159 VIXL_UNIMPLEMENTED();
2160 break;
2161 default:
2162 VIXL_UNIMPLEMENTED();
2163 }
2164}
2165
2166void Simulator::Simulate_ZdH_ZnH_ZmH_imm(const Instruction* instr) {
2167 SimVRegister& zd = ReadVRegister(instr->GetRd());
2168 USE(zd);
2169 SimVRegister& zn = ReadVRegister(instr->GetRn());
2170 USE(zn);
2171
2172 switch (form_hash_) {
2173 case Hash("mul_z_zzi_h"):
2174 VIXL_UNIMPLEMENTED();
2175 break;
2176 case Hash("sqdmulh_z_zzi_h"):
2177 VIXL_UNIMPLEMENTED();
2178 break;
2179 case Hash("sqrdmulh_z_zzi_h"):
2180 VIXL_UNIMPLEMENTED();
2181 break;
2182 default:
2183 VIXL_UNIMPLEMENTED();
2184 }
2185}
2186
2187void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2188 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2189 USE(pg);
2190 SimVRegister& zd = ReadVRegister(instr->GetRd());
2191 USE(zd);
2192 SimVRegister& zn = ReadVRegister(instr->GetRn());
2193 USE(zn);
2194
2195 switch (form_hash_) {
2196 case Hash("fcvtnt_z_p_z_d2s"):
2197 VIXL_UNIMPLEMENTED();
2198 break;
2199 case Hash("fcvtx_z_p_z_d2s"):
2200 VIXL_UNIMPLEMENTED();
2201 break;
2202 case Hash("fcvtxnt_z_p_z_d2s"):
2203 VIXL_UNIMPLEMENTED();
2204 break;
2205 default:
2206 VIXL_UNIMPLEMENTED();
2207 }
2208}
2209
2210void Simulator::Simulate_ZdS_PgM_ZnH(const Instruction* instr) {
2211 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2212 USE(pg);
2213 SimVRegister& zd = ReadVRegister(instr->GetRd());
2214 USE(zd);
2215 SimVRegister& zn = ReadVRegister(instr->GetRn());
2216 USE(zn);
2217
2218 switch (form_hash_) {
2219 case Hash("fcvtlt_z_p_z_h2s"):
2220 VIXL_UNIMPLEMENTED();
2221 break;
2222 default:
2223 VIXL_UNIMPLEMENTED();
2224 }
2225}
2226
2227void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002228 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002229 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002230 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002231 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002232 SimVRegister result;
2233
2234 if (vform != kFormatVnS) {
2235 VIXL_UNIMPLEMENTED();
2236 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002237
2238 switch (form_hash_) {
2239 case Hash("urecpe_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002240 urecpe(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002241 break;
2242 case Hash("ursqrte_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002243 ursqrte(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002244 break;
2245 default:
2246 VIXL_UNIMPLEMENTED();
2247 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002248 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002249}
2250
Martyn Capewell6bf28752020-08-05 11:57:06 +01002251void Simulator::Simulate_ZdS_ZnS_ZmS_imm(const Instruction* instr) {
2252 SimVRegister& zd = ReadVRegister(instr->GetRd());
2253 USE(zd);
2254 SimVRegister& zn = ReadVRegister(instr->GetRn());
2255 USE(zn);
2256
2257 switch (form_hash_) {
2258 case Hash("mul_z_zzi_s"):
2259 VIXL_UNIMPLEMENTED();
2260 break;
2261 case Hash("sqdmulh_z_zzi_s"):
2262 VIXL_UNIMPLEMENTED();
2263 break;
2264 case Hash("sqrdmulh_z_zzi_s"):
2265 VIXL_UNIMPLEMENTED();
2266 break;
2267 default:
2268 VIXL_UNIMPLEMENTED();
2269 }
2270}
2271
2272void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002273 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002274 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002275 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002276 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002277 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002278
2279 switch (form_hash_) {
2280 case Hash("flogb_z_p_z"):
Martyn Capewell342876b2021-02-24 16:34:33 +00002281 vform = instr->GetSVEVectorFormat(17);
2282 flogb(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002283 break;
2284 case Hash("sqabs_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002285 abs(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002286 break;
2287 case Hash("sqneg_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002288 neg(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002289 break;
2290 default:
2291 VIXL_UNIMPLEMENTED();
2292 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002293 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002294}
2295
2296void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell030875c2020-10-21 18:08:05 +01002297 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002298 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002299 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002300 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002301 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell030875c2020-10-21 18:08:05 +01002302 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002303
Martyn Capewell030875c2020-10-21 18:08:05 +01002304 VIXL_ASSERT(form_hash_ == Hash("histcnt_z_p_zz"));
2305 if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
Martyn Capewell710ec6f2020-10-22 16:56:17 +01002306 histogram(vform, result, pg, zn, zm);
Martyn Capewell030875c2020-10-21 18:08:05 +01002307 mov_zeroing(vform, zd, pg, result);
2308 } else {
2309 VIXL_UNIMPLEMENTED();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002310 }
2311}
2312
Martyn Capewell6bf28752020-08-05 11:57:06 +01002313void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002314 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002315 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002316 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002317 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002318 SimVRegister result;
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002319 bool do_bext = false;
2320
Martyn Capewell6bf28752020-08-05 11:57:06 +01002321 switch (form_hash_) {
2322 case Hash("bdep_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002323 bdep(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002324 break;
2325 case Hash("bext_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002326 do_bext = true;
2327 VIXL_FALLTHROUGH();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002328 case Hash("bgrp_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002329 bgrp(vform, zd, zn, zm, do_bext);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002330 break;
2331 case Hash("eorbt_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002332 rotate_elements_right(vform, result, zm, 1);
2333 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2334 mov_alternating(vform, zd, result, 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002335 break;
2336 case Hash("eortb_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002337 rotate_elements_right(vform, result, zm, -1);
2338 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2339 mov_alternating(vform, zd, result, 1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002340 break;
2341 case Hash("mul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002342 mul(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002343 break;
2344 case Hash("smulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002345 smulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002346 break;
2347 case Hash("sqdmulh_z_zz"):
Martyn Capewell310326b2021-01-12 16:33:22 +00002348 sqdmulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002349 break;
2350 case Hash("sqrdmulh_z_zz"):
Martyn Capewell310326b2021-01-12 16:33:22 +00002351 sqrdmulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002352 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002353 case Hash("umulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002354 umulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002355 break;
2356 default:
2357 VIXL_UNIMPLEMENTED();
2358 }
2359}
2360
2361void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002362 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002363 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002364 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002365 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002366
2367 SimVRegister zm_b, zm_t;
TatWai Chong236e7ae2020-09-13 14:55:04 -07002368 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2369 pack_even_elements(vform_half, zm_b, zm);
2370 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002371
2372 switch (form_hash_) {
2373 case Hash("saddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002374 saddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002375 break;
2376 case Hash("saddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002377 saddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002378 break;
2379 case Hash("ssubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002380 ssubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002381 break;
2382 case Hash("ssubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002383 ssubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002384 break;
2385 case Hash("uaddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002386 uaddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002387 break;
2388 case Hash("uaddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002389 uaddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002390 break;
2391 case Hash("usubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002392 usubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002393 break;
2394 case Hash("usubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002395 usubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002396 break;
2397 default:
2398 VIXL_UNIMPLEMENTED();
2399 }
2400}
2401
2402void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2403 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002404 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell78743b62020-09-09 11:08:57 +01002405
2406 std::pair<int, int> shift_and_lane_size =
2407 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2408 int lane_size = shift_and_lane_size.second;
2409 VIXL_ASSERT((lane_size >= 0) &&
2410 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2411 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2412 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002413
2414 switch (form_hash_) {
2415 case Hash("sli_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002416 // Shift distance is computed differently for left shifts. Convert the
2417 // result.
2418 shift_dist = (8 << lane_size) - shift_dist;
2419 sli(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002420 break;
2421 case Hash("sri_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002422 sri(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002423 break;
2424 default:
2425 VIXL_UNIMPLEMENTED();
2426 }
2427}
2428
Martyn Capewellea9b4072020-10-09 11:25:26 +01002429void Simulator::SimulateSVENarrow(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002430 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002431 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellb5636e52020-09-17 11:21:29 +01002432 SimVRegister result;
2433
2434 std::pair<int, int> shift_and_lane_size =
2435 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2436 int lane_size = shift_and_lane_size.second;
2437 VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2438 (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2439 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewellea9b4072020-10-09 11:25:26 +01002440 int right_shift_dist = shift_and_lane_size.first;
Martyn Capewellb5636e52020-09-17 11:21:29 +01002441 bool top = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002442
2443 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002444 case Hash("sqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002445 top = true;
2446 VIXL_FALLTHROUGH();
2447 case Hash("sqxtnb_z_zz"):
2448 sqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002449 break;
2450 case Hash("sqxtunt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002451 top = true;
2452 VIXL_FALLTHROUGH();
2453 case Hash("sqxtunb_z_zz"):
2454 sqxtun(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002455 break;
2456 case Hash("uqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002457 top = true;
2458 VIXL_FALLTHROUGH();
2459 case Hash("uqxtnb_z_zz"):
2460 uqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002461 break;
Martyn Capewellea9b4072020-10-09 11:25:26 +01002462 case Hash("rshrnt_z_zi"):
2463 top = true;
2464 VIXL_FALLTHROUGH();
2465 case Hash("rshrnb_z_zi"):
2466 rshrn(vform, result, zn, right_shift_dist);
2467 break;
2468 case Hash("shrnt_z_zi"):
2469 top = true;
2470 VIXL_FALLTHROUGH();
2471 case Hash("shrnb_z_zi"):
2472 shrn(vform, result, zn, right_shift_dist);
2473 break;
2474 case Hash("sqrshrnt_z_zi"):
2475 top = true;
2476 VIXL_FALLTHROUGH();
2477 case Hash("sqrshrnb_z_zi"):
2478 sqrshrn(vform, result, zn, right_shift_dist);
2479 break;
2480 case Hash("sqrshrunt_z_zi"):
2481 top = true;
2482 VIXL_FALLTHROUGH();
2483 case Hash("sqrshrunb_z_zi"):
2484 sqrshrun(vform, result, zn, right_shift_dist);
2485 break;
2486 case Hash("sqshrnt_z_zi"):
2487 top = true;
2488 VIXL_FALLTHROUGH();
2489 case Hash("sqshrnb_z_zi"):
2490 sqshrn(vform, result, zn, right_shift_dist);
2491 break;
2492 case Hash("sqshrunt_z_zi"):
2493 top = true;
2494 VIXL_FALLTHROUGH();
2495 case Hash("sqshrunb_z_zi"):
2496 sqshrun(vform, result, zn, right_shift_dist);
2497 break;
2498 case Hash("uqrshrnt_z_zi"):
2499 top = true;
2500 VIXL_FALLTHROUGH();
2501 case Hash("uqrshrnb_z_zi"):
2502 uqrshrn(vform, result, zn, right_shift_dist);
2503 break;
2504 case Hash("uqshrnt_z_zi"):
2505 top = true;
2506 VIXL_FALLTHROUGH();
2507 case Hash("uqshrnb_z_zi"):
2508 uqshrn(vform, result, zn, right_shift_dist);
2509 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002510 default:
2511 VIXL_UNIMPLEMENTED();
2512 }
Martyn Capewellb5636e52020-09-17 11:21:29 +01002513
2514 if (top) {
2515 // Keep even elements, replace odd elements with the results.
2516 xtn(vform, zd, zd);
2517 zip1(vform, zd, zd, result);
2518 } else {
2519 // Zero odd elements, replace even elements with the results.
2520 SimVRegister zero;
2521 zero.Clear();
2522 zip1(vform, zd, result, zero);
2523 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002524}
2525
Martyn Capewellc7275e62020-09-24 14:06:07 +01002526void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
Martyn Capewella2d7fbb2020-09-18 18:22:54 +01002527 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002528 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002529 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002530 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002531 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2532
2533 // Construct temporary registers containing the even (bottom) and odd (top)
2534 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002535 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2536 pack_even_elements(vform_half, zn_b, zn);
2537 pack_even_elements(vform_half, zm_b, zm);
2538 pack_odd_elements(vform_half, zn_t, zn);
2539 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewellc7275e62020-09-24 14:06:07 +01002540
2541 switch (form_hash_) {
2542 case Hash("sabdlb_z_zz"):
2543 sabdl(vform, zd, zn_b, zm_b);
2544 break;
2545 case Hash("sabdlt_z_zz"):
2546 sabdl(vform, zd, zn_t, zm_t);
2547 break;
2548 case Hash("saddlb_z_zz"):
2549 saddl(vform, zd, zn_b, zm_b);
2550 break;
2551 case Hash("saddlbt_z_zz"):
2552 saddl(vform, zd, zn_b, zm_t);
2553 break;
2554 case Hash("saddlt_z_zz"):
2555 saddl(vform, zd, zn_t, zm_t);
2556 break;
2557 case Hash("ssublb_z_zz"):
2558 ssubl(vform, zd, zn_b, zm_b);
2559 break;
2560 case Hash("ssublbt_z_zz"):
2561 ssubl(vform, zd, zn_b, zm_t);
2562 break;
2563 case Hash("ssublt_z_zz"):
2564 ssubl(vform, zd, zn_t, zm_t);
2565 break;
2566 case Hash("ssubltb_z_zz"):
2567 ssubl(vform, zd, zn_t, zm_b);
2568 break;
2569 case Hash("uabdlb_z_zz"):
2570 uabdl(vform, zd, zn_b, zm_b);
2571 break;
2572 case Hash("uabdlt_z_zz"):
2573 uabdl(vform, zd, zn_t, zm_t);
2574 break;
2575 case Hash("uaddlb_z_zz"):
2576 uaddl(vform, zd, zn_b, zm_b);
2577 break;
2578 case Hash("uaddlt_z_zz"):
2579 uaddl(vform, zd, zn_t, zm_t);
2580 break;
2581 case Hash("usublb_z_zz"):
2582 usubl(vform, zd, zn_b, zm_b);
2583 break;
2584 case Hash("usublt_z_zz"):
2585 usubl(vform, zd, zn_t, zm_t);
2586 break;
Martyn Capewell67d2f822020-10-13 16:39:33 +01002587 case Hash("sabalb_z_zzz"):
2588 sabal(vform, zd, zn_b, zm_b);
2589 break;
2590 case Hash("sabalt_z_zzz"):
2591 sabal(vform, zd, zn_t, zm_t);
2592 break;
2593 case Hash("uabalb_z_zzz"):
2594 uabal(vform, zd, zn_b, zm_b);
2595 break;
2596 case Hash("uabalt_z_zzz"):
2597 uabal(vform, zd, zn_t, zm_t);
2598 break;
Martyn Capewellc7275e62020-09-24 14:06:07 +01002599 default:
2600 VIXL_UNIMPLEMENTED();
2601 }
2602}
2603
TatWai Chong236e7ae2020-09-13 14:55:04 -07002604void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2605 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewellc7275e62020-09-24 14:06:07 +01002606 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002607 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002608 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong236e7ae2020-09-13 14:55:04 -07002609 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2610 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2611 pack_even_elements(vform_half, zn_b, zn);
2612 pack_even_elements(vform_half, zm_b, zm);
2613 pack_odd_elements(vform_half, zn_t, zn);
2614 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002615
2616 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002617 case Hash("pmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002618 // '00' is reserved for Q-sized lane.
2619 if (vform == kFormatVnB) {
2620 VIXL_UNIMPLEMENTED();
2621 }
2622 pmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002623 break;
2624 case Hash("pmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002625 // '00' is reserved for Q-sized lane.
2626 if (vform == kFormatVnB) {
2627 VIXL_UNIMPLEMENTED();
2628 }
2629 pmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002630 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002631 case Hash("smullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002632 smull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002633 break;
2634 case Hash("smullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002635 smull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002636 break;
2637 case Hash("sqdmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002638 sqdmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002639 break;
2640 case Hash("sqdmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002641 sqdmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002642 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002643 case Hash("umullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002644 umull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002645 break;
2646 case Hash("umullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002647 umull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002648 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002649 default:
2650 VIXL_UNIMPLEMENTED();
2651 }
2652}
2653
Martyn Capewell8b9c44b2020-10-14 18:21:42 +01002654void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2655 SimVRegister& zd = ReadVRegister(instr->GetRd());
2656 SimVRegister& zm = ReadVRegister(instr->GetRm());
2657 SimVRegister& zn = ReadVRegister(instr->GetRn());
2658 SimVRegister result;
2659 bool top = false;
2660
2661 VectorFormat vform_src = instr->GetSVEVectorFormat();
2662 if (vform_src == kFormatVnB) {
2663 VIXL_UNIMPLEMENTED();
2664 }
2665 VectorFormat vform = VectorFormatHalfWidth(vform_src);
2666
2667 switch (form_hash_) {
2668 case Hash("addhnt_z_zz"):
2669 top = true;
2670 VIXL_FALLTHROUGH();
2671 case Hash("addhnb_z_zz"):
2672 addhn(vform, result, zn, zm);
2673 break;
2674 case Hash("raddhnt_z_zz"):
2675 top = true;
2676 VIXL_FALLTHROUGH();
2677 case Hash("raddhnb_z_zz"):
2678 raddhn(vform, result, zn, zm);
2679 break;
2680 case Hash("rsubhnt_z_zz"):
2681 top = true;
2682 VIXL_FALLTHROUGH();
2683 case Hash("rsubhnb_z_zz"):
2684 rsubhn(vform, result, zn, zm);
2685 break;
2686 case Hash("subhnt_z_zz"):
2687 top = true;
2688 VIXL_FALLTHROUGH();
2689 case Hash("subhnb_z_zz"):
2690 subhn(vform, result, zn, zm);
2691 break;
2692 default:
2693 VIXL_UNIMPLEMENTED();
2694 }
2695
2696 if (top) {
2697 // Keep even elements, replace odd elements with the results.
2698 xtn(vform, zd, zd);
2699 zip1(vform, zd, zd, result);
2700 } else {
2701 // Zero odd elements, replace even elements with the results.
2702 SimVRegister zero;
2703 zero.Clear();
2704 zip1(vform, zd, result, zero);
2705 }
2706}
2707
Martyn Capewellea9b4072020-10-09 11:25:26 +01002708void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002709 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002710 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell51dcef92020-10-08 16:04:12 +01002711 SimVRegister zn_b, zn_t;
2712
2713 std::pair<int, int> shift_and_lane_size =
2714 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2715 int lane_size = shift_and_lane_size.second;
2716 VIXL_ASSERT((lane_size >= 0) &&
2717 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2718 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2719 int right_shift_dist = shift_and_lane_size.first;
2720 int left_shift_dist = (8 << lane_size) - right_shift_dist;
2721
2722 // Construct temporary registers containing the even (bottom) and odd (top)
2723 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002724 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2725 pack_even_elements(vform_half, zn_b, zn);
2726 pack_odd_elements(vform_half, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002727
2728 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002729 case Hash("sshllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002730 sshll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002731 break;
2732 case Hash("sshllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002733 sshll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002734 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002735 case Hash("ushllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002736 ushll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002737 break;
2738 case Hash("ushllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002739 ushll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002740 break;
2741 default:
2742 VIXL_UNIMPLEMENTED();
2743 }
2744}
2745
2746void Simulator::Simulate_ZdaD_ZnD_ZmD_imm(const Instruction* instr) {
2747 SimVRegister& zda = ReadVRegister(instr->GetRd());
2748 USE(zda);
2749 SimVRegister& zn = ReadVRegister(instr->GetRn());
2750 USE(zn);
2751
2752 switch (form_hash_) {
2753 case Hash("mla_z_zzzi_d"):
2754 VIXL_UNIMPLEMENTED();
2755 break;
2756 case Hash("mls_z_zzzi_d"):
2757 VIXL_UNIMPLEMENTED();
2758 break;
2759 case Hash("sqrdmlah_z_zzzi_d"):
2760 VIXL_UNIMPLEMENTED();
2761 break;
2762 case Hash("sqrdmlsh_z_zzzi_d"):
2763 VIXL_UNIMPLEMENTED();
2764 break;
2765 default:
2766 VIXL_UNIMPLEMENTED();
2767 }
2768}
2769
Martyn Capewell6bf28752020-08-05 11:57:06 +01002770void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2771 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002772 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong05545662020-12-18 20:53:05 -08002773 SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
2774
2775 SimVRegister temp, zm_idx, zn_b, zn_t;
2776 Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
2777 dup_elements_to_segments(kFormatVnS, temp, zm, index);
2778 pack_even_elements(kFormatVnS, zm_idx, temp);
2779 pack_even_elements(kFormatVnS, zn_b, zn);
2780 pack_odd_elements(kFormatVnS, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002781
2782 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002783 case Hash("sqdmlalb_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002784 sqdmlal(kFormatVnD, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002785 break;
2786 case Hash("sqdmlalt_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002787 sqdmlal(kFormatVnD, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002788 break;
2789 case Hash("sqdmlslb_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002790 sqdmlsl(kFormatVnD, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002791 break;
2792 case Hash("sqdmlslt_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002793 sqdmlsl(kFormatVnD, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002794 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002795 default:
2796 VIXL_UNIMPLEMENTED();
2797 }
2798}
2799
2800void Simulator::Simulate_ZdaH_ZnH_ZmH_imm(const Instruction* instr) {
2801 SimVRegister& zda = ReadVRegister(instr->GetRd());
2802 USE(zda);
2803 SimVRegister& zn = ReadVRegister(instr->GetRn());
2804 USE(zn);
2805
2806 switch (form_hash_) {
2807 case Hash("mla_z_zzzi_h"):
2808 VIXL_UNIMPLEMENTED();
2809 break;
2810 case Hash("mls_z_zzzi_h"):
2811 VIXL_UNIMPLEMENTED();
2812 break;
2813 case Hash("sqrdmlah_z_zzzi_h"):
2814 VIXL_UNIMPLEMENTED();
2815 break;
2816 case Hash("sqrdmlsh_z_zzzi_h"):
2817 VIXL_UNIMPLEMENTED();
2818 break;
2819 default:
2820 VIXL_UNIMPLEMENTED();
2821 }
2822}
2823
Martyn Capewell6bf28752020-08-05 11:57:06 +01002824void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2825 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002826 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002827 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chongba9a1482020-10-01 20:25:54 -07002828
2829 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2830 pack_even_elements(kFormatVnH, zn_b, zn);
2831 pack_even_elements(kFormatVnH, zm_b, zm);
2832 pack_odd_elements(kFormatVnH, zn_t, zn);
2833 pack_odd_elements(kFormatVnH, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002834
2835 switch (form_hash_) {
2836 case Hash("fmlalb_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002837 fmlal(kFormatVnS, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002838 break;
2839 case Hash("fmlalt_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002840 fmlal(kFormatVnS, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002841 break;
2842 case Hash("fmlslb_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002843 fmlsl(kFormatVnS, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002844 break;
2845 case Hash("fmlslt_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002846 fmlsl(kFormatVnS, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002847 break;
2848 default:
2849 VIXL_UNIMPLEMENTED();
2850 }
2851}
2852
2853void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2854 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002855 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong05545662020-12-18 20:53:05 -08002856 SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
2857
2858 SimVRegister temp, zm_idx, zn_b, zn_t;
2859 Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
2860 dup_elements_to_segments(kFormatVnH, temp, zm, index);
2861 pack_even_elements(kFormatVnH, zm_idx, temp);
2862 pack_even_elements(kFormatVnH, zn_b, zn);
2863 pack_odd_elements(kFormatVnH, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002864
2865 switch (form_hash_) {
2866 case Hash("fmlalb_z_zzzi_s"):
Martyn Capewell317abf72021-02-24 17:12:46 +00002867 fmlal(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002868 break;
2869 case Hash("fmlalt_z_zzzi_s"):
Martyn Capewell317abf72021-02-24 17:12:46 +00002870 fmlal(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002871 break;
2872 case Hash("fmlslb_z_zzzi_s"):
Martyn Capewell317abf72021-02-24 17:12:46 +00002873 fmlsl(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002874 break;
2875 case Hash("fmlslt_z_zzzi_s"):
Martyn Capewell317abf72021-02-24 17:12:46 +00002876 fmlsl(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002877 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002878 case Hash("sqdmlalb_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002879 sqdmlal(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002880 break;
2881 case Hash("sqdmlalt_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002882 sqdmlal(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002883 break;
2884 case Hash("sqdmlslb_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002885 sqdmlsl(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002886 break;
2887 case Hash("sqdmlslt_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002888 sqdmlsl(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002889 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002890 default:
2891 VIXL_UNIMPLEMENTED();
2892 }
2893}
2894
2895void Simulator::Simulate_ZdaS_ZnS_ZmS_imm(const Instruction* instr) {
2896 SimVRegister& zda = ReadVRegister(instr->GetRd());
2897 USE(zda);
2898 SimVRegister& zn = ReadVRegister(instr->GetRn());
2899 USE(zn);
2900
2901 switch (form_hash_) {
2902 case Hash("mla_z_zzzi_s"):
2903 VIXL_UNIMPLEMENTED();
2904 break;
2905 case Hash("mls_z_zzzi_s"):
2906 VIXL_UNIMPLEMENTED();
2907 break;
2908 case Hash("sqrdmlah_z_zzzi_s"):
2909 VIXL_UNIMPLEMENTED();
2910 break;
2911 case Hash("sqrdmlsh_z_zzzi_s"):
2912 VIXL_UNIMPLEMENTED();
2913 break;
2914 default:
2915 VIXL_UNIMPLEMENTED();
2916 }
2917}
2918
Martyn Capewell6bf28752020-08-05 11:57:06 +01002919void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
TatWai Chong602aa122020-10-05 16:28:27 -07002920 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002921 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002922 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002923 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong602aa122020-10-05 16:28:27 -07002924 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002925
2926 switch (form_hash_) {
2927 case Hash("sadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002928 sadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002929 break;
2930 case Hash("uadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002931 uadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002932 break;
2933 default:
2934 VIXL_UNIMPLEMENTED();
2935 }
TatWai Chong602aa122020-10-05 16:28:27 -07002936 mov_merging(vform, zda, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002937}
2938
Martyn Capewellc4b56bb2020-10-14 15:45:14 +01002939void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
2940 VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
2941 SimVRegister& zda = ReadVRegister(instr->GetRd());
2942 SimVRegister& zm = ReadVRegister(instr->GetRm());
2943 SimVRegister& zn = ReadVRegister(instr->GetRn());
2944
2945 SimVRegister not_zn;
2946 not_(vform, not_zn, zn);
2947
2948 switch (form_hash_) {
2949 case Hash("adclb_z_zzz"):
2950 adcl(vform, zda, zn, zm, /* top = */ false);
2951 break;
2952 case Hash("adclt_z_zzz"):
2953 adcl(vform, zda, zn, zm, /* top = */ true);
2954 break;
2955 case Hash("sbclb_z_zzz"):
2956 adcl(vform, zda, not_zn, zm, /* top = */ false);
2957 break;
2958 case Hash("sbclt_z_zzz"):
2959 adcl(vform, zda, not_zn, zm, /* top = */ true);
2960 break;
2961 default:
2962 VIXL_UNIMPLEMENTED();
2963 }
2964}
2965
Martyn Capewell6bf28752020-08-05 11:57:06 +01002966void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002967 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002968 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002969 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002970 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002971
2972 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002973 case Hash("saba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002974 saba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002975 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002976 case Hash("sqrdmlah_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07002977 sqrdmlah(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002978 break;
2979 case Hash("sqrdmlsh_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07002980 sqrdmlsh(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002981 break;
2982 case Hash("uaba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002983 uaba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002984 break;
2985 default:
2986 VIXL_UNIMPLEMENTED();
2987 }
2988}
2989
TatWai Chongada6b352020-11-06 13:48:09 -08002990void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002991 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002992 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chongada6b352020-11-06 13:48:09 -08002993 int rot = instr->ExtractBits(11, 10) * 90;
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00002994 // vform and zm are only valid for the vector form of instruction.
TatWai Chong6b67f6e2020-12-03 23:37:57 -08002995 VectorFormat vform = instr->GetSVEVectorFormat();
2996 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002997
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00002998 // Inputs for indexed form of instruction.
2999 SimVRegister& zm_h = ReadVRegister(instr->ExtractBits(18, 16));
3000 SimVRegister& zm_s = ReadVRegister(instr->ExtractBits(19, 16));
3001 int idx_h = instr->ExtractBits(20, 19);
3002 int idx_s = instr->ExtractBit(20);
3003
Martyn Capewell6bf28752020-08-05 11:57:06 +01003004 switch (form_hash_) {
3005 case Hash("cmla_z_zzz"):
TatWai Chongada6b352020-11-06 13:48:09 -08003006 cmla(vform, zda, zda, zn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003007 break;
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003008 case Hash("cmla_z_zzzi_h"):
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00003009 cmla(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003010 break;
3011 case Hash("cmla_z_zzzi_s"):
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00003012 cmla(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003013 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003014 case Hash("sqrdcmlah_z_zzz"):
TatWai Chongada6b352020-11-06 13:48:09 -08003015 sqrdcmlah(vform, zda, zda, zn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003016 break;
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003017 case Hash("sqrdcmlah_z_zzzi_h"):
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00003018 sqrdcmlah(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003019 break;
3020 case Hash("sqrdcmlah_z_zzzi_s"):
Martyn Capewell0ebd9e72021-02-23 17:08:24 +00003021 sqrdcmlah(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003022 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003023 default:
3024 VIXL_UNIMPLEMENTED();
3025 }
3026}
3027
3028void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003029 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003030 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003031
3032 std::pair<int, int> shift_and_lane_size =
3033 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3034 int lane_size = shift_and_lane_size.second;
3035 VIXL_ASSERT((lane_size >= 0) &&
3036 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3037 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3038 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003039
3040 switch (form_hash_) {
3041 case Hash("srsra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003042 srsra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003043 break;
3044 case Hash("ssra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003045 ssra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003046 break;
3047 case Hash("ursra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003048 ursra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003049 break;
3050 case Hash("usra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003051 usra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003052 break;
3053 default:
3054 VIXL_UNIMPLEMENTED();
3055 }
3056}
3057
3058void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
Martyn Capewell4a454b42020-11-19 18:18:10 +00003059 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003060 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003061 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003062 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell4a454b42020-11-19 18:18:10 +00003063
TatWai Chong5c080292020-12-13 03:57:15 -08003064 SimVRegister zero, zn_b, zm_b, zn_t, zm_t;
3065 zero.Clear();
3066
Martyn Capewell4a454b42020-11-19 18:18:10 +00003067 VectorFormat vform_half = VectorFormatHalfWidth(vform);
TatWai Chong5c080292020-12-13 03:57:15 -08003068 uzp1(vform_half, zn_b, zn, zero);
3069 uzp1(vform_half, zm_b, zm, zero);
3070 uzp2(vform_half, zn_t, zn, zero);
3071 uzp2(vform_half, zm_t, zm, zero);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003072
3073 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003074 case Hash("smlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003075 smlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003076 break;
3077 case Hash("smlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003078 smlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003079 break;
3080 case Hash("smlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003081 smlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003082 break;
3083 case Hash("smlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003084 smlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003085 break;
3086 case Hash("sqdmlalb_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003087 sqdmlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003088 break;
3089 case Hash("sqdmlalbt_z_zzz"):
TatWai Chong5c080292020-12-13 03:57:15 -08003090 sqdmlal(vform, zda, zn_b, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003091 break;
3092 case Hash("sqdmlalt_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003093 sqdmlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003094 break;
3095 case Hash("sqdmlslb_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003096 sqdmlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003097 break;
3098 case Hash("sqdmlslbt_z_zzz"):
TatWai Chong5c080292020-12-13 03:57:15 -08003099 sqdmlsl(vform, zda, zn_b, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003100 break;
3101 case Hash("sqdmlslt_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003102 sqdmlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003103 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003104 case Hash("umlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003105 umlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003106 break;
3107 case Hash("umlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003108 umlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003109 break;
3110 case Hash("umlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003111 umlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003112 break;
3113 case Hash("umlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003114 umlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003115 break;
3116 default:
3117 VIXL_UNIMPLEMENTED();
3118 }
3119}
3120
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003121void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
Martyn Capewellf4da2202020-11-03 17:42:57 +00003122 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003123 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003124 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellf4da2202020-11-03 17:42:57 +00003125 int rot = instr->ExtractBits(11, 10) * 90;
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003126 unsigned zm_code = instr->GetRm();
3127 int index = -1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003128
3129 switch (form_hash_) {
3130 case Hash("cdot_z_zzz"):
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003131 // Nothing to do.
3132 break;
3133 case Hash("cdot_z_zzzi_s"):
3134 index = zm_code >> 3;
3135 zm_code &= 0x7;
3136 break;
3137 case Hash("cdot_z_zzzi_d"):
3138 index = zm_code >> 4;
3139 zm_code &= 0xf;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003140 break;
3141 default:
3142 VIXL_UNIMPLEMENTED();
3143 }
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003144
3145 SimVRegister temp;
3146 SimVRegister& zm = ReadVRegister(zm_code);
3147 if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3148 cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003149}
3150
Martyn Capewellb1b95782020-10-23 15:59:49 +01003151void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3152 VectorFormat vform = kFormatVnD;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003153 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003154 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellb1b95782020-10-23 15:59:49 +01003155 SimVRegister& zk = ReadVRegister(instr->GetRn());
3156 SimVRegister temp;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003157
3158 switch (form_hash_) {
3159 case Hash("bcax_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003160 bic(vform, temp, zm, zk);
3161 eor(vform, zdn, temp, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003162 break;
3163 case Hash("bsl1n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003164 not_(vform, temp, zdn);
3165 bsl(vform, zdn, zk, temp, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003166 break;
3167 case Hash("bsl2n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003168 not_(vform, temp, zm);
3169 bsl(vform, zdn, zk, zdn, temp);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003170 break;
3171 case Hash("bsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003172 bsl(vform, zdn, zk, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003173 break;
3174 case Hash("eor3_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003175 eor(vform, temp, zdn, zm);
3176 eor(vform, zdn, temp, zk);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003177 break;
3178 case Hash("nbsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003179 bsl(vform, zdn, zk, zdn, zm);
3180 not_(vform, zdn, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003181 break;
3182 default:
3183 VIXL_UNIMPLEMENTED();
3184 }
3185}
3186
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003187void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3188 VectorFormat vform = instr->GetSVEVectorFormat();
3189 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3190 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3191 SimVRegister& zm = ReadVRegister(instr->GetRn());
3192 SimVRegister result;
3193
3194 switch (form_hash_) {
3195 case Hash("shadd_z_p_zz"):
3196 add(vform, result, zdn, zm).Halve(vform);
3197 break;
3198 case Hash("shsub_z_p_zz"):
3199 sub(vform, result, zdn, zm).Halve(vform);
3200 break;
3201 case Hash("shsubr_z_p_zz"):
3202 sub(vform, result, zm, zdn).Halve(vform);
3203 break;
3204 case Hash("srhadd_z_p_zz"):
3205 add(vform, result, zdn, zm).Halve(vform).Round(vform);
3206 break;
3207 case Hash("uhadd_z_p_zz"):
3208 add(vform, result, zdn, zm).Uhalve(vform);
3209 break;
3210 case Hash("uhsub_z_p_zz"):
3211 sub(vform, result, zdn, zm).Uhalve(vform);
3212 break;
3213 case Hash("uhsubr_z_p_zz"):
3214 sub(vform, result, zm, zdn).Uhalve(vform);
3215 break;
3216 case Hash("urhadd_z_p_zz"):
3217 add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3218 break;
3219 default:
3220 VIXL_UNIMPLEMENTED();
Martyn Capewell9b532192020-09-15 16:20:11 +01003221 break;
3222 }
3223 mov_merging(vform, zdn, pg, result);
3224}
3225
3226void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3227 VectorFormat vform = instr->GetSVEVectorFormat();
3228 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3229 SimVRegister& zm = ReadVRegister(instr->GetRn());
3230 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3231 SimVRegister result;
3232
3233 switch (form_hash_) {
3234 case Hash("sqadd_z_p_zz"):
3235 add(vform, result, zdn, zm).SignedSaturate(vform);
3236 break;
3237 case Hash("sqsub_z_p_zz"):
3238 sub(vform, result, zdn, zm).SignedSaturate(vform);
3239 break;
3240 case Hash("sqsubr_z_p_zz"):
3241 sub(vform, result, zm, zdn).SignedSaturate(vform);
3242 break;
3243 case Hash("suqadd_z_p_zz"):
3244 suqadd(vform, result, zdn, zm);
3245 break;
3246 case Hash("uqadd_z_p_zz"):
3247 add(vform, result, zdn, zm).UnsignedSaturate(vform);
3248 break;
3249 case Hash("uqsub_z_p_zz"):
3250 sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3251 break;
3252 case Hash("uqsubr_z_p_zz"):
3253 sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3254 break;
3255 case Hash("usqadd_z_p_zz"):
3256 usqadd(vform, result, zdn, zm);
3257 break;
3258 default:
3259 VIXL_UNIMPLEMENTED();
3260 break;
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003261 }
3262 mov_merging(vform, zdn, pg, result);
3263}
3264
Martyn Capewellfa1e2112020-09-16 16:53:09 +01003265void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3266 VectorFormat vform = instr->GetSVEVectorFormat();
3267 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3268 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3269 SimVRegister& zm = ReadVRegister(instr->GetRn());
3270 SimVRegister result;
3271
3272 switch (form_hash_) {
3273 case Hash("addp_z_p_zz"):
3274 addp(vform, result, zdn, zm);
3275 break;
3276 case Hash("smaxp_z_p_zz"):
3277 smaxp(vform, result, zdn, zm);
3278 break;
3279 case Hash("sminp_z_p_zz"):
3280 sminp(vform, result, zdn, zm);
3281 break;
3282 case Hash("umaxp_z_p_zz"):
3283 umaxp(vform, result, zdn, zm);
3284 break;
3285 case Hash("uminp_z_p_zz"):
3286 uminp(vform, result, zdn, zm);
3287 break;
3288 default:
3289 VIXL_UNIMPLEMENTED();
3290 break;
3291 }
3292 mov_merging(vform, zdn, pg, result);
3293}
3294
Martyn Capewell6bf28752020-08-05 11:57:06 +01003295void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003296 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003297 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003298 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003299 SimVRegister& zm = ReadVRegister(instr->GetRn());
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003300 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003301
3302 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003303 case Hash("faddp_z_p_zz"):
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003304 faddp(vform, result, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003305 break;
3306 case Hash("fmaxnmp_z_p_zz"):
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003307 fmaxnmp(vform, result, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003308 break;
3309 case Hash("fmaxp_z_p_zz"):
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003310 fmaxp(vform, result, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003311 break;
3312 case Hash("fminnmp_z_p_zz"):
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003313 fminnmp(vform, result, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003314 break;
3315 case Hash("fminp_z_p_zz"):
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003316 fminp(vform, result, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003317 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003318 default:
3319 VIXL_UNIMPLEMENTED();
3320 }
Martyn Capewell14e4ddd2021-02-24 16:42:03 +00003321 mov_merging(vform, zdn, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003322}
3323
3324void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3325 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003326 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003327
3328 std::pair<int, int> shift_and_lane_size =
3329 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3330 unsigned lane_size = shift_and_lane_size.second;
3331 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3332 int right_shift_dist = shift_and_lane_size.first;
3333 int left_shift_dist = (8 << lane_size) - right_shift_dist;
3334 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003335
3336 switch (form_hash_) {
3337 case Hash("sqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003338 sqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003339 break;
3340 case Hash("sqshlu_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003341 sqshlu(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003342 break;
3343 case Hash("srshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003344 sshr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003345 break;
3346 case Hash("uqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003347 uqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003348 break;
3349 case Hash("urshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003350 ushr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003351 break;
3352 default:
3353 VIXL_UNIMPLEMENTED();
3354 }
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003355 mov_merging(vform, zdn, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003356}
3357
Martyn Capewell97ca8062020-10-23 14:45:14 +01003358void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3359 VIXL_ASSERT(form_hash_ == Hash("xar_z_zzi"));
3360
3361 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3362 SimVRegister& zm = ReadVRegister(instr->GetRn());
3363
3364 std::pair<int, int> shift_and_lane_size =
3365 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3366 unsigned lane_size = shift_and_lane_size.second;
3367 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3368 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3369 int shift_dist = shift_and_lane_size.first;
Martyn Capewellb1b95782020-10-23 15:59:49 +01003370 eor(vform, zdn, zdn, zm);
Martyn Capewell97ca8062020-10-23 14:45:14 +01003371 ror(vform, zdn, zdn, shift_dist);
3372}
3373
Martyn Capewell6bf28752020-08-05 11:57:06 +01003374void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
Martyn Capewell819dcf92020-10-20 16:07:09 +01003375 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003376 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003377 SimVRegister& zm = ReadVRegister(instr->GetRn());
Martyn Capewell819dcf92020-10-20 16:07:09 +01003378 int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003379
3380 switch (form_hash_) {
3381 case Hash("cadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003382 cadd(vform, zdn, zdn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003383 break;
3384 case Hash("sqcadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003385 cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003386 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003387 default:
3388 VIXL_UNIMPLEMENTED();
3389 }
3390}
3391
3392void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3393 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003394 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003395 uint64_t xm = ReadXRegister(instr->GetRm());
3396
3397 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3398 int msize = -1;
3399 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003400
3401 switch (form_hash_) {
3402 case Hash("ldnt1b_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003403 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003404 break;
3405 case Hash("ldnt1d_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003406 msize = 3;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003407 break;
3408 case Hash("ldnt1h_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003409 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003410 break;
3411 case Hash("ldnt1sb_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003412 msize = 0;
3413 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003414 break;
3415 case Hash("ldnt1sh_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003416 msize = 1;
3417 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003418 break;
3419 case Hash("ldnt1sw_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003420 msize = 2;
3421 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003422 break;
3423 case Hash("ldnt1w_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003424 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003425 break;
3426 default:
3427 VIXL_UNIMPLEMENTED();
3428 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003429 addr.SetMsizeInBytesLog2(msize);
3430 SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003431}
3432
3433void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3434 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003435 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003436 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003437
Martyn Capewell1ac83572020-11-11 16:15:58 +00003438 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3439 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_d_64_unscaled")) ||
3440 (form_hash_ == Hash("stnt1d_z_p_ar_d_64_unscaled")) ||
3441 (form_hash_ == Hash("stnt1h_z_p_ar_d_64_unscaled")) ||
3442 (form_hash_ == Hash("stnt1w_z_p_ar_d_64_unscaled")));
3443
3444 addr.SetMsizeInBytesLog2(
3445 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3446 SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003447}
3448
3449void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3450 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003451 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003452 uint64_t xm = ReadXRegister(instr->GetRm());
3453
3454 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3455 int msize = -1;
3456 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003457
3458 switch (form_hash_) {
3459 case Hash("ldnt1b_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003460 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003461 break;
3462 case Hash("ldnt1h_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003463 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003464 break;
3465 case Hash("ldnt1sb_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003466 msize = 0;
3467 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003468 break;
3469 case Hash("ldnt1sh_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003470 msize = 1;
3471 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003472 break;
3473 case Hash("ldnt1w_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003474 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003475 break;
3476 default:
3477 VIXL_UNIMPLEMENTED();
3478 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003479 addr.SetMsizeInBytesLog2(msize);
3480 SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003481}
3482
3483void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3484 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003485 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003486 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003487
Martyn Capewell1ac83572020-11-11 16:15:58 +00003488 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3489 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_s_x32_unscaled")) ||
3490 (form_hash_ == Hash("stnt1h_z_p_ar_s_x32_unscaled")) ||
3491 (form_hash_ == Hash("stnt1w_z_p_ar_s_x32_unscaled")));
3492
3493 addr.SetMsizeInBytesLog2(
3494 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3495 SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003496}
3497
Jacob Bramley18c97bd2019-01-18 16:01:08 +00003498void Simulator::VisitReserved(const Instruction* instr) {
3499 // UDF is the only instruction in this group, and the Decoder is precise here.
3500 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3501
3502 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3503 reinterpret_cast<const void*>(instr),
3504 instr->GetInstructionBits());
3505 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3506}
3507
3508
Alexandre Ramesd3832962016-07-04 15:03:43 +01003509void Simulator::VisitUnimplemented(const Instruction* instr) {
3510 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3511 reinterpret_cast<const void*>(instr),
3512 instr->GetInstructionBits());
3513 VIXL_UNIMPLEMENTED();
3514}
3515
3516
3517void Simulator::VisitUnallocated(const Instruction* instr) {
3518 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3519 reinterpret_cast<const void*>(instr),
3520 instr->GetInstructionBits());
3521 VIXL_UNIMPLEMENTED();
3522}
3523
3524
3525void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3526 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3527 (instr->Mask(PCRelAddressingMask) == ADRP));
3528
3529 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3530}
3531
3532
3533void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3534 switch (instr->Mask(UnconditionalBranchMask)) {
3535 case BL:
3536 WriteLr(instr->GetNextInstruction());
3537 VIXL_FALLTHROUGH();
3538 case B:
3539 WritePc(instr->GetImmPCOffsetTarget());
3540 break;
3541 default:
3542 VIXL_UNREACHABLE();
3543 }
3544}
3545
3546
3547void Simulator::VisitConditionalBranch(const Instruction* instr) {
3548 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3549 if (ConditionPassed(instr->GetConditionBranch())) {
3550 WritePc(instr->GetImmPCOffsetTarget());
3551 }
3552}
3553
Martyn Capewellcb963f72018-10-22 15:25:28 +01003554BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3555 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3556 case BLR:
3557 case BLRAA:
3558 case BLRAB:
3559 case BLRAAZ:
3560 case BLRABZ:
3561 return BranchAndLink;
3562 case BR:
3563 case BRAA:
3564 case BRAB:
3565 case BRAAZ:
3566 case BRABZ:
3567 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3568 !PcIsInGuardedPage()) {
3569 return BranchFromUnguardedOrToIP;
3570 }
3571 return BranchFromGuardedNotToIP;
3572 }
3573 return DefaultBType;
3574}
Alexandre Ramesd3832962016-07-04 15:03:43 +01003575
3576void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003577 bool authenticate = false;
3578 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01003579 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01003580 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003581
3582 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3583 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01003584 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003585 VIXL_FALLTHROUGH();
3586 case BR:
3587 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01003588 break;
3589
3590 case BLRAAZ:
3591 case BLRABZ:
3592 link = true;
3593 VIXL_FALLTHROUGH();
3594 case BRAAZ:
3595 case BRABZ:
3596 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003597 break;
3598
3599 case BLRAA:
3600 case BLRAB:
3601 link = true;
3602 VIXL_FALLTHROUGH();
3603 case BRAA:
3604 case BRAB:
3605 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003606 context = ReadXRegister(instr->GetRd());
3607 break;
3608
3609 case RETAA:
3610 case RETAB:
3611 authenticate = true;
3612 addr = ReadXRegister(kLinkRegCode);
3613 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003614 break;
3615 default:
3616 VIXL_UNREACHABLE();
3617 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003618
3619 if (link) {
3620 WriteLr(instr->GetNextInstruction());
3621 }
3622
3623 if (authenticate) {
3624 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3625 addr = AuthPAC(addr, context, key, kInstructionPointer);
3626
3627 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3628 if (((addr >> error_lsb) & 0x3) != 0x0) {
3629 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3630 }
3631 }
3632
Martyn Capewellcb963f72018-10-22 15:25:28 +01003633 WritePc(Instruction::Cast(addr));
3634 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003635}
3636
3637
3638void Simulator::VisitTestBranch(const Instruction* instr) {
3639 unsigned bit_pos =
3640 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3641 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3642 bool take_branch = false;
3643 switch (instr->Mask(TestBranchMask)) {
3644 case TBZ:
3645 take_branch = bit_zero;
3646 break;
3647 case TBNZ:
3648 take_branch = !bit_zero;
3649 break;
3650 default:
3651 VIXL_UNIMPLEMENTED();
3652 }
3653 if (take_branch) {
3654 WritePc(instr->GetImmPCOffsetTarget());
3655 }
3656}
3657
3658
3659void Simulator::VisitCompareBranch(const Instruction* instr) {
3660 unsigned rt = instr->GetRt();
3661 bool take_branch = false;
3662 switch (instr->Mask(CompareBranchMask)) {
3663 case CBZ_w:
3664 take_branch = (ReadWRegister(rt) == 0);
3665 break;
3666 case CBZ_x:
3667 take_branch = (ReadXRegister(rt) == 0);
3668 break;
3669 case CBNZ_w:
3670 take_branch = (ReadWRegister(rt) != 0);
3671 break;
3672 case CBNZ_x:
3673 take_branch = (ReadXRegister(rt) != 0);
3674 break;
3675 default:
3676 VIXL_UNIMPLEMENTED();
3677 }
3678 if (take_branch) {
3679 WritePc(instr->GetImmPCOffsetTarget());
3680 }
3681}
3682
3683
3684void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3685 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3686 bool set_flags = instr->GetFlagsUpdate();
3687 int64_t new_val = 0;
3688 Instr operation = instr->Mask(AddSubOpMask);
3689
3690 switch (operation) {
3691 case ADD:
3692 case ADDS: {
3693 new_val = AddWithCarry(reg_size,
3694 set_flags,
3695 ReadRegister(reg_size,
3696 instr->GetRn(),
3697 instr->GetRnMode()),
3698 op2);
3699 break;
3700 }
3701 case SUB:
3702 case SUBS: {
3703 new_val = AddWithCarry(reg_size,
3704 set_flags,
3705 ReadRegister(reg_size,
3706 instr->GetRn(),
3707 instr->GetRnMode()),
3708 ~op2,
3709 1);
3710 break;
3711 }
3712 default:
3713 VIXL_UNREACHABLE();
3714 }
3715
3716 WriteRegister(reg_size,
3717 instr->GetRd(),
3718 new_val,
3719 LogRegWrites,
3720 instr->GetRdMode());
3721}
3722
3723
3724void Simulator::VisitAddSubShifted(const Instruction* instr) {
3725 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3726 int64_t op2 = ShiftOperand(reg_size,
3727 ReadRegister(reg_size, instr->GetRm()),
3728 static_cast<Shift>(instr->GetShiftDP()),
3729 instr->GetImmDPShift());
3730 AddSubHelper(instr, op2);
3731}
3732
3733
3734void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3735 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01003736 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003737 AddSubHelper(instr, op2);
3738}
3739
3740
3741void Simulator::VisitAddSubExtended(const Instruction* instr) {
3742 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3743 int64_t op2 = ExtendValue(reg_size,
3744 ReadRegister(reg_size, instr->GetRm()),
3745 static_cast<Extend>(instr->GetExtendMode()),
3746 instr->GetImmExtendShift());
3747 AddSubHelper(instr, op2);
3748}
3749
3750
3751void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3752 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3753 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3754 int64_t new_val;
3755
3756 if ((instr->Mask(AddSubOpMask) == SUB) ||
3757 (instr->Mask(AddSubOpMask) == SUBS)) {
3758 op2 = ~op2;
3759 }
3760
3761 new_val = AddWithCarry(reg_size,
3762 instr->GetFlagsUpdate(),
3763 ReadRegister(reg_size, instr->GetRn()),
3764 op2,
3765 ReadC());
3766
3767 WriteRegister(reg_size, instr->GetRd(), new_val);
3768}
3769
3770
Alexander Gilday2487f142018-11-05 13:07:27 +00003771void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3772 switch (instr->Mask(RotateRightIntoFlagsMask)) {
3773 case RMIF: {
3774 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3775 unsigned shift = instr->GetImmRMIFRotation();
3776 unsigned mask = instr->GetNzcv();
3777 uint64_t rotated = RotateRight(value, shift, kXRegSize);
3778
3779 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3780 break;
3781 }
3782 }
3783}
3784
3785
3786void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3787 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3788 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3789
3790 unsigned sign_bit = (value >> msb) & 1;
3791 unsigned overflow_bit = (value >> (msb + 1)) & 1;
3792 ReadNzcv().SetN(sign_bit);
3793 ReadNzcv().SetZ((value << (31 - msb)) == 0);
3794 ReadNzcv().SetV(sign_bit ^ overflow_bit);
3795}
3796
3797
Alexandre Ramesd3832962016-07-04 15:03:43 +01003798void Simulator::VisitLogicalShifted(const Instruction* instr) {
3799 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3800 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3801 unsigned shift_amount = instr->GetImmDPShift();
3802 int64_t op2 = ShiftOperand(reg_size,
3803 ReadRegister(reg_size, instr->GetRm()),
3804 shift_type,
3805 shift_amount);
3806 if (instr->Mask(NOT) == NOT) {
3807 op2 = ~op2;
3808 }
3809 LogicalHelper(instr, op2);
3810}
3811
3812
3813void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3814 LogicalHelper(instr, instr->GetImmLogical());
3815}
3816
3817
3818void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3819 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3820 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3821 int64_t result = 0;
3822 bool update_flags = false;
3823
3824 // Switch on the logical operation, stripping out the NOT bit, as it has a
3825 // different meaning for logical immediate instructions.
3826 switch (instr->Mask(LogicalOpMask & ~NOT)) {
3827 case ANDS:
3828 update_flags = true;
3829 VIXL_FALLTHROUGH();
3830 case AND:
3831 result = op1 & op2;
3832 break;
3833 case ORR:
3834 result = op1 | op2;
3835 break;
3836 case EOR:
3837 result = op1 ^ op2;
3838 break;
3839 default:
3840 VIXL_UNIMPLEMENTED();
3841 }
3842
3843 if (update_flags) {
3844 ReadNzcv().SetN(CalcNFlag(result, reg_size));
3845 ReadNzcv().SetZ(CalcZFlag(result));
3846 ReadNzcv().SetC(0);
3847 ReadNzcv().SetV(0);
3848 LogSystemRegister(NZCV);
3849 }
3850
3851 WriteRegister(reg_size,
3852 instr->GetRd(),
3853 result,
3854 LogRegWrites,
3855 instr->GetRdMode());
3856}
3857
3858
3859void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3860 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3861 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3862}
3863
3864
3865void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3866 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3867}
3868
3869
3870void Simulator::ConditionalCompareHelper(const Instruction* instr,
3871 int64_t op2) {
3872 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3873 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3874
3875 if (ConditionPassed(instr->GetCondition())) {
3876 // If the condition passes, set the status flags to the result of comparing
3877 // the operands.
3878 if (instr->Mask(ConditionalCompareMask) == CCMP) {
3879 AddWithCarry(reg_size, true, op1, ~op2, 1);
3880 } else {
3881 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3882 AddWithCarry(reg_size, true, op1, op2, 0);
3883 }
3884 } else {
3885 // If the condition fails, set the status flags to the nzcv immediate.
3886 ReadNzcv().SetFlags(instr->GetNzcv());
3887 LogSystemRegister(NZCV);
3888 }
3889}
3890
3891
3892void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3893 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3894 LoadStoreHelper(instr, offset, Offset);
3895}
3896
3897
3898void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3899 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3900}
3901
3902
3903void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3904 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3905}
3906
3907
3908void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3909 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3910}
3911
3912
Alexander Gilday311edf22018-10-29 13:41:41 +00003913template <typename T1, typename T2>
3914void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
3915 unsigned rt = instr->GetRt();
3916 unsigned rn = instr->GetRn();
3917
3918 unsigned element_size = sizeof(T2);
3919 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3920 int offset = instr->GetImmLS();
3921 address += offset;
3922
3923 // Verify that the address is available to the host.
3924 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3925
3926 // Check the alignment of `address`.
3927 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3928 VIXL_ALIGNMENT_EXCEPTION();
3929 }
3930
3931 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
3932
3933 // Approximate load-acquire by issuing a full barrier after the load.
3934 __sync_synchronize();
3935
Jacob Bramley423e5422019-11-13 19:15:55 +00003936 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003937}
3938
3939
3940template <typename T>
3941void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
3942 unsigned rt = instr->GetRt();
3943 unsigned rn = instr->GetRn();
3944
3945 unsigned element_size = sizeof(T);
3946 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3947 int offset = instr->GetImmLS();
3948 address += offset;
3949
3950 // Verify that the address is available to the host.
3951 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3952
3953 // Check the alignment of `address`.
3954 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3955 VIXL_ALIGNMENT_EXCEPTION();
3956 }
3957
3958 // Approximate store-release by issuing a full barrier after the load.
3959 __sync_synchronize();
3960
3961 Memory::Write<T>(address, ReadRegister<T>(rt));
3962
Jacob Bramley423e5422019-11-13 19:15:55 +00003963 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003964}
3965
3966
3967void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
3968 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
3969 case LDAPURB:
3970 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
3971 break;
3972 case LDAPURH:
3973 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
3974 break;
3975 case LDAPUR_w:
3976 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
3977 break;
3978 case LDAPUR_x:
3979 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
3980 break;
3981 case LDAPURSB_w:
3982 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
3983 break;
3984 case LDAPURSB_x:
3985 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
3986 break;
3987 case LDAPURSH_w:
3988 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
3989 break;
3990 case LDAPURSH_x:
3991 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
3992 break;
3993 case LDAPURSW:
3994 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
3995 break;
3996 case STLURB:
3997 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
3998 break;
3999 case STLURH:
4000 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4001 break;
4002 case STLUR_w:
4003 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4004 break;
4005 case STLUR_x:
4006 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4007 break;
4008 }
4009}
4010
4011
Alexander Gilday75605592018-11-01 09:30:29 +00004012void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4013 unsigned dst = instr->GetRt();
4014 unsigned addr_reg = instr->GetRn();
4015
4016 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4017
4018 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4019 address = AuthPAC(address, 0, key, kDataPointer);
4020
4021 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4022 if (((address >> error_lsb) & 0x3) != 0x0) {
4023 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4024 }
4025
4026
4027 if ((addr_reg == 31) && ((address % 16) != 0)) {
4028 // When the base register is SP the stack pointer is required to be
4029 // quadword aligned prior to the address calculation and write-backs.
4030 // Misalignment will cause a stack alignment fault.
4031 VIXL_ALIGNMENT_EXCEPTION();
4032 }
4033
4034 int64_t offset = instr->GetImmLSPAC();
4035 address += offset;
4036
4037 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4038 // Pre-index mode.
4039 VIXL_ASSERT(offset != 0);
4040 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4041 }
4042
4043 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4044
4045 // Verify that the calculated address is available to the host.
4046 VIXL_ASSERT(address == addr_ptr);
4047
4048 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
4049 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00004050 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00004051}
4052
4053
Alexandre Ramesd3832962016-07-04 15:03:43 +01004054void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4055 Extend ext = static_cast<Extend>(instr->GetExtendMode());
4056 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4057 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4058
4059 int64_t offset =
4060 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4061 LoadStoreHelper(instr, offset, Offset);
4062}
4063
4064
4065void Simulator::LoadStoreHelper(const Instruction* instr,
4066 int64_t offset,
4067 AddrMode addrmode) {
4068 unsigned srcdst = instr->GetRt();
4069 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4070
Jacob Bramley423e5422019-11-13 19:15:55 +00004071 bool rt_is_vreg = false;
4072 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004073 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4074 switch (op) {
4075 case LDRB_w:
4076 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004077 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004078 break;
4079 case LDRH_w:
4080 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004081 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004082 break;
4083 case LDR_w:
4084 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004085 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004086 break;
4087 case LDR_x:
4088 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004089 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004090 break;
4091 case LDRSB_w:
4092 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004093 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004094 break;
4095 case LDRSH_w:
4096 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004097 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004098 break;
4099 case LDRSB_x:
4100 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004101 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004102 break;
4103 case LDRSH_x:
4104 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004105 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004106 break;
4107 case LDRSW_x:
4108 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004109 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004110 break;
4111 case LDR_b:
4112 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004113 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004114 break;
4115 case LDR_h:
4116 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004117 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004118 break;
4119 case LDR_s:
4120 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004121 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004122 break;
4123 case LDR_d:
4124 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004125 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004126 break;
4127 case LDR_q:
4128 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004129 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004130 break;
4131
4132 case STRB_w:
4133 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
4134 break;
4135 case STRH_w:
4136 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
4137 break;
4138 case STR_w:
4139 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
4140 break;
4141 case STR_x:
4142 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
4143 break;
4144 case STR_b:
4145 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004146 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004147 break;
4148 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01004149 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004150 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004151 break;
4152 case STR_s:
4153 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004154 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004155 break;
4156 case STR_d:
4157 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004158 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004159 break;
4160 case STR_q:
4161 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004162 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004163 break;
4164
4165 // Ignore prfm hint instructions.
4166 case PRFM:
4167 break;
4168
4169 default:
4170 VIXL_UNIMPLEMENTED();
4171 }
4172
Jacob Bramley423e5422019-11-13 19:15:55 +00004173 // Print a detailed trace (including the memory address).
4174 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004175 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00004176 unsigned result_size = extend ? extend_to_size : access_size;
4177 PrintRegisterFormat print_format =
4178 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4179 : GetPrintRegisterFormatForSize(result_size);
4180
Alexandre Ramesd3832962016-07-04 15:03:43 +01004181 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004182 if (rt_is_vreg) {
4183 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004184 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004185 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004186 }
4187 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004188 if (rt_is_vreg) {
4189 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004190 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004191 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004192 }
4193 } else {
4194 VIXL_ASSERT(op == PRFM);
4195 }
4196
4197 local_monitor_.MaybeClear();
4198}
4199
4200
4201void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4202 LoadStorePairHelper(instr, Offset);
4203}
4204
4205
4206void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4207 LoadStorePairHelper(instr, PreIndex);
4208}
4209
4210
4211void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4212 LoadStorePairHelper(instr, PostIndex);
4213}
4214
4215
4216void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4217 LoadStorePairHelper(instr, Offset);
4218}
4219
4220
4221void Simulator::LoadStorePairHelper(const Instruction* instr,
4222 AddrMode addrmode) {
4223 unsigned rt = instr->GetRt();
4224 unsigned rt2 = instr->GetRt2();
4225 int element_size = 1 << instr->GetSizeLSPair();
4226 int64_t offset = instr->GetImmLSPair() * element_size;
4227 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4228 uintptr_t address2 = address + element_size;
4229
4230 LoadStorePairOp op =
4231 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4232
4233 // 'rt' and 'rt2' can only be aliased for stores.
4234 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4235
Jacob Bramley423e5422019-11-13 19:15:55 +00004236 bool rt_is_vreg = false;
4237 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004238 switch (op) {
4239 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4240 // will print a more detailed log.
4241 case LDP_w: {
4242 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4243 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
4244 break;
4245 }
4246 case LDP_s: {
4247 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
4248 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004249 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004250 break;
4251 }
4252 case LDP_x: {
4253 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4254 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
4255 break;
4256 }
4257 case LDP_d: {
4258 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
4259 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004260 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004261 break;
4262 }
4263 case LDP_q: {
4264 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
4265 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004266 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004267 break;
4268 }
4269 case LDPSW_x: {
4270 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
4271 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004272 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004273 break;
4274 }
4275 case STP_w: {
4276 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4277 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
4278 break;
4279 }
4280 case STP_s: {
4281 Memory::Write<float>(address, ReadSRegister(rt));
4282 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004283 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004284 break;
4285 }
4286 case STP_x: {
4287 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4288 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
4289 break;
4290 }
4291 case STP_d: {
4292 Memory::Write<double>(address, ReadDRegister(rt));
4293 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004294 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004295 break;
4296 }
4297 case STP_q: {
4298 Memory::Write<qreg_t>(address, ReadQRegister(rt));
4299 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004300 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004301 break;
4302 }
4303 default:
4304 VIXL_UNREACHABLE();
4305 }
4306
Jacob Bramley423e5422019-11-13 19:15:55 +00004307 // Print a detailed trace (including the memory address).
4308 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4309 PrintRegisterFormat print_format =
4310 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4311 : GetPrintRegisterFormatForSize(result_size);
4312
Alexandre Ramesd3832962016-07-04 15:03:43 +01004313 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004314 if (rt_is_vreg) {
4315 LogVRead(rt, print_format, address);
4316 LogVRead(rt2, print_format, address2);
4317 } else if (sign_extend) {
4318 LogExtendingRead(rt, print_format, element_size, address);
4319 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004320 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004321 LogRead(rt, print_format, address);
4322 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004323 }
4324 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004325 if (rt_is_vreg) {
4326 LogVWrite(rt, print_format, address);
4327 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004328 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004329 LogWrite(rt, print_format, address);
4330 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004331 }
4332 }
4333
4334 local_monitor_.MaybeClear();
4335}
4336
4337
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004338template <typename T>
4339void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4340 unsigned rs = instr->GetRs();
4341 unsigned rt = instr->GetRt();
4342 unsigned rn = instr->GetRn();
4343
4344 unsigned element_size = sizeof(T);
4345 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4346
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004347 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4348
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004349 bool is_acquire = instr->ExtractBit(22) == 1;
4350 bool is_release = instr->ExtractBit(15) == 1;
4351
4352 T comparevalue = ReadRegister<T>(rs);
4353 T newvalue = ReadRegister<T>(rt);
4354
4355 // The architecture permits that the data read clears any exclusive monitors
4356 // associated with that location, even if the compare subsequently fails.
4357 local_monitor_.Clear();
4358
4359 T data = Memory::Read<T>(address);
4360 if (is_acquire) {
4361 // Approximate load-acquire by issuing a full barrier after the load.
4362 __sync_synchronize();
4363 }
4364
4365 if (data == comparevalue) {
4366 if (is_release) {
4367 // Approximate store-release by issuing a full barrier before the store.
4368 __sync_synchronize();
4369 }
4370 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00004371 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004372 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004373 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004374 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004375}
4376
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004377
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004378template <typename T>
4379void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4380 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4381 unsigned rs = instr->GetRs();
4382 unsigned rt = instr->GetRt();
4383 unsigned rn = instr->GetRn();
4384
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004385 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004386
4387 unsigned element_size = sizeof(T);
4388 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004389
4390 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4391
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004392 uint64_t address2 = address + element_size;
4393
4394 bool is_acquire = instr->ExtractBit(22) == 1;
4395 bool is_release = instr->ExtractBit(15) == 1;
4396
4397 T comparevalue_high = ReadRegister<T>(rs + 1);
4398 T comparevalue_low = ReadRegister<T>(rs);
4399 T newvalue_high = ReadRegister<T>(rt + 1);
4400 T newvalue_low = ReadRegister<T>(rt);
4401
4402 // The architecture permits that the data read clears any exclusive monitors
4403 // associated with that location, even if the compare subsequently fails.
4404 local_monitor_.Clear();
4405
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004406 T data_low = Memory::Read<T>(address);
4407 T data_high = Memory::Read<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004408
4409 if (is_acquire) {
4410 // Approximate load-acquire by issuing a full barrier after the load.
4411 __sync_synchronize();
4412 }
4413
4414 bool same =
4415 (data_high == comparevalue_high) && (data_low == comparevalue_low);
4416 if (same) {
4417 if (is_release) {
4418 // Approximate store-release by issuing a full barrier before the store.
4419 __sync_synchronize();
4420 }
4421
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004422 Memory::Write<T>(address, newvalue_low);
4423 Memory::Write<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004424 }
4425
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004426 WriteRegister<T>(rs + 1, data_high, NoRegLog);
4427 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004428
Jacob Bramley423e5422019-11-13 19:15:55 +00004429 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004430 LogRead(rs, format, address);
4431 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004432
4433 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004434 LogWrite(rt, format, address);
4435 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004436 }
4437}
4438
Jacob Bramley85a9c102019-12-09 17:48:29 +00004439bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4440 // To simulate fault-tolerant loads, we need to know what host addresses we
4441 // can access without generating a real fault. One way to do that is to
4442 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
4443 // and less intrusive than using (global) signal handlers.
4444 //
4445 // [1]: https://stackoverflow.com/questions/7134590
4446
4447 size_t written = 0;
4448 bool can_read = true;
4449 // `write` will normally return after one invocation, but it is allowed to
4450 // handle only part of the operation, so wrap it in a loop.
4451 while (can_read && (written < size)) {
4452 ssize_t result = write(dummy_pipe_fd_[1],
4453 reinterpret_cast<void*>(address + written),
4454 size - written);
4455 if (result > 0) {
4456 written += result;
4457 } else {
4458 switch (result) {
4459 case -EPERM:
4460 case -EFAULT:
4461 // The address range is not accessible.
4462 // `write` is supposed to return -EFAULT in this case, but in practice
4463 // it seems to return -EPERM, so we accept that too.
4464 can_read = false;
4465 break;
4466 case -EINTR:
4467 // The call was interrupted by a signal. Just try again.
4468 break;
4469 default:
4470 // Any other error is fatal.
4471 VIXL_ABORT();
4472 }
4473 }
4474 }
4475 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4476 // the dummy data is buffered. As before, we expect to drain the whole write
4477 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
4478 // function is primarily intended to implement SVE fault-tolerant loads, so
4479 // the maximum Z register size is a good default buffer size.
4480 char buffer[kZRegMaxSizeInBytes];
4481 while (written > 0) {
4482 ssize_t result = read(dummy_pipe_fd_[0],
4483 reinterpret_cast<void*>(buffer),
4484 sizeof(buffer));
4485 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4486 // we've read everything that was written, so treat 0 as an error.
4487 if (result > 0) {
4488 VIXL_ASSERT(static_cast<size_t>(result) <= written);
4489 written -= result;
4490 } else {
4491 // For -EINTR, just try again. We can't handle any other error.
4492 VIXL_CHECK(result == -EINTR);
4493 }
4494 }
4495
4496 return can_read;
4497}
Alexandre Ramesd3832962016-07-04 15:03:43 +01004498
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004499void Simulator::PrintExclusiveAccessWarning() {
4500 if (print_exclusive_access_warning_) {
4501 fprintf(stderr,
4502 "%sWARNING:%s VIXL simulator support for "
4503 "load-/store-/clear-exclusive "
4504 "instructions is limited. Refer to the README for details.%s\n",
4505 clr_warning,
4506 clr_warning_message,
4507 clr_normal);
4508 print_exclusive_access_warning_ = false;
4509 }
4510}
4511
Alexandre Ramesd3832962016-07-04 15:03:43 +01004512void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004513 LoadStoreExclusive op =
4514 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4515
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004516 switch (op) {
4517 case CAS_w:
4518 case CASA_w:
4519 case CASL_w:
4520 case CASAL_w:
4521 CompareAndSwapHelper<uint32_t>(instr);
4522 break;
4523 case CAS_x:
4524 case CASA_x:
4525 case CASL_x:
4526 case CASAL_x:
4527 CompareAndSwapHelper<uint64_t>(instr);
4528 break;
4529 case CASB:
4530 case CASAB:
4531 case CASLB:
4532 case CASALB:
4533 CompareAndSwapHelper<uint8_t>(instr);
4534 break;
4535 case CASH:
4536 case CASAH:
4537 case CASLH:
4538 case CASALH:
4539 CompareAndSwapHelper<uint16_t>(instr);
4540 break;
4541 case CASP_w:
4542 case CASPA_w:
4543 case CASPL_w:
4544 case CASPAL_w:
4545 CompareAndSwapPairHelper<uint32_t>(instr);
4546 break;
4547 case CASP_x:
4548 case CASPA_x:
4549 case CASPL_x:
4550 case CASPAL_x:
4551 CompareAndSwapPairHelper<uint64_t>(instr);
4552 break;
4553 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004554 PrintExclusiveAccessWarning();
4555
4556 unsigned rs = instr->GetRs();
4557 unsigned rt = instr->GetRt();
4558 unsigned rt2 = instr->GetRt2();
4559 unsigned rn = instr->GetRn();
4560
4561 bool is_exclusive = !instr->GetLdStXNotExclusive();
4562 bool is_acquire_release =
4563 !is_exclusive || instr->GetLdStXAcquireRelease();
4564 bool is_load = instr->GetLdStXLoad();
4565 bool is_pair = instr->GetLdStXPair();
4566
4567 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4568 unsigned access_size = is_pair ? element_size * 2 : element_size;
4569 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4570
4571 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4572
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004573 if (is_load) {
4574 if (is_exclusive) {
4575 local_monitor_.MarkExclusive(address, access_size);
4576 } else {
4577 // Any non-exclusive load can clear the local monitor as a side
4578 // effect. We don't need to do this, but it is useful to stress the
4579 // simulated code.
4580 local_monitor_.Clear();
4581 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004582
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004583 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4584 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00004585 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004586 switch (op) {
4587 case LDXRB_w:
4588 case LDAXRB_w:
4589 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004590 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004591 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004592 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004593 break;
4594 case LDXRH_w:
4595 case LDAXRH_w:
4596 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004597 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004598 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004599 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004600 break;
4601 case LDXR_w:
4602 case LDAXR_w:
4603 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004604 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004605 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004606 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004607 break;
4608 case LDXR_x:
4609 case LDAXR_x:
4610 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004611 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004612 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004613 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004614 break;
4615 case LDXP_w:
4616 case LDAXP_w:
4617 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4618 WriteWRegister(rt2,
4619 Memory::Read<uint32_t>(address + element_size),
4620 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004621 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004622 break;
4623 case LDXP_x:
4624 case LDAXP_x:
4625 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4626 WriteXRegister(rt2,
4627 Memory::Read<uint64_t>(address + element_size),
4628 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004629 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004630 break;
4631 default:
4632 VIXL_UNREACHABLE();
4633 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004634
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004635 if (is_acquire_release) {
4636 // Approximate load-acquire by issuing a full barrier after the load.
4637 __sync_synchronize();
4638 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004639
Jacob Bramley423e5422019-11-13 19:15:55 +00004640 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4641 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004642 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004643 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004644 }
4645 } else {
4646 if (is_acquire_release) {
4647 // Approximate store-release by issuing a full barrier before the
4648 // store.
4649 __sync_synchronize();
4650 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004651
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004652 bool do_store = true;
4653 if (is_exclusive) {
4654 do_store = local_monitor_.IsExclusive(address, access_size) &&
4655 global_monitor_.IsExclusive(address, access_size);
4656 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004657
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004658 // - All exclusive stores explicitly clear the local monitor.
4659 local_monitor_.Clear();
4660 } else {
4661 // - Any other store can clear the local monitor as a side effect.
4662 local_monitor_.MaybeClear();
4663 }
4664
4665 if (do_store) {
4666 switch (op) {
4667 case STXRB_w:
4668 case STLXRB_w:
4669 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004670 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004671 Memory::Write<uint8_t>(address, ReadWRegister(rt));
4672 break;
4673 case STXRH_w:
4674 case STLXRH_w:
4675 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004676 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004677 Memory::Write<uint16_t>(address, ReadWRegister(rt));
4678 break;
4679 case STXR_w:
4680 case STLXR_w:
4681 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004682 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004683 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4684 break;
4685 case STXR_x:
4686 case STLXR_x:
4687 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004688 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004689 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4690 break;
4691 case STXP_w:
4692 case STLXP_w:
4693 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4694 Memory::Write<uint32_t>(address + element_size,
4695 ReadWRegister(rt2));
4696 break;
4697 case STXP_x:
4698 case STLXP_x:
4699 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4700 Memory::Write<uint64_t>(address + element_size,
4701 ReadXRegister(rt2));
4702 break;
4703 default:
4704 VIXL_UNREACHABLE();
4705 }
4706
Jacob Bramley423e5422019-11-13 19:15:55 +00004707 PrintRegisterFormat format =
4708 GetPrintRegisterFormatForSize(element_size);
4709 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004710 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004711 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004712 }
4713 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004714 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004715 }
4716}
4717
Jacob Bramleyca789742018-09-13 14:25:46 +01004718template <typename T>
4719void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4720 unsigned rs = instr->GetRs();
4721 unsigned rt = instr->GetRt();
4722 unsigned rn = instr->GetRn();
4723
4724 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4725 bool is_release = instr->ExtractBit(22) == 1;
4726
4727 unsigned element_size = sizeof(T);
4728 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4729
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004730 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004731
4732 T value = ReadRegister<T>(rs);
4733
4734 T data = Memory::Read<T>(address);
4735
4736 if (is_acquire) {
4737 // Approximate load-acquire by issuing a full barrier after the load.
4738 __sync_synchronize();
4739 }
4740
4741 T result = 0;
4742 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4743 case LDADDOp:
4744 result = data + value;
4745 break;
4746 case LDCLROp:
4747 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4748 result = data & ~value;
4749 break;
4750 case LDEOROp:
4751 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4752 result = data ^ value;
4753 break;
4754 case LDSETOp:
4755 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4756 result = data | value;
4757 break;
4758
4759 // Signed/Unsigned difference is done via the templated type T.
4760 case LDSMAXOp:
4761 case LDUMAXOp:
4762 result = (data > value) ? data : value;
4763 break;
4764 case LDSMINOp:
4765 case LDUMINOp:
4766 result = (data > value) ? value : data;
4767 break;
4768 }
4769
4770 if (is_release) {
4771 // Approximate store-release by issuing a full barrier before the store.
4772 __sync_synchronize();
4773 }
4774
4775 Memory::Write<T>(address, result);
4776 WriteRegister<T>(rt, data, NoRegLog);
4777
Jacob Bramley423e5422019-11-13 19:15:55 +00004778 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4779 LogRead(rt, format, address);
4780 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004781}
4782
4783template <typename T>
4784void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4785 unsigned rs = instr->GetRs();
4786 unsigned rt = instr->GetRt();
4787 unsigned rn = instr->GetRn();
4788
4789 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4790 bool is_release = instr->ExtractBit(22) == 1;
4791
4792 unsigned element_size = sizeof(T);
4793 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4794
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004795 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004796
4797 T data = Memory::Read<T>(address);
4798 if (is_acquire) {
4799 // Approximate load-acquire by issuing a full barrier after the load.
4800 __sync_synchronize();
4801 }
4802
4803 if (is_release) {
4804 // Approximate store-release by issuing a full barrier before the store.
4805 __sync_synchronize();
4806 }
4807 Memory::Write<T>(address, ReadRegister<T>(rs));
4808
4809 WriteRegister<T>(rt, data);
4810
Jacob Bramley423e5422019-11-13 19:15:55 +00004811 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4812 LogRead(rt, format, address);
4813 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004814}
4815
4816template <typename T>
4817void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4818 unsigned rt = instr->GetRt();
4819 unsigned rn = instr->GetRn();
4820
4821 unsigned element_size = sizeof(T);
4822 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4823
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004824 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4825
Jacob Bramleyca789742018-09-13 14:25:46 +01004826 WriteRegister<T>(rt, Memory::Read<T>(address));
4827
4828 // Approximate load-acquire by issuing a full barrier after the load.
4829 __sync_synchronize();
4830
Jacob Bramley423e5422019-11-13 19:15:55 +00004831 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004832}
4833
4834#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4835 V(LDADD) \
4836 V(LDCLR) \
4837 V(LDEOR) \
4838 V(LDSET) \
4839 V(LDUMAX) \
4840 V(LDUMIN)
4841
4842#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4843 V(LDSMAX) \
4844 V(LDSMIN)
4845
4846void Simulator::VisitAtomicMemory(const Instruction* instr) {
4847 switch (instr->Mask(AtomicMemoryMask)) {
4848// clang-format off
4849#define SIM_FUNC_B(A) \
4850 case A##B: \
4851 case A##AB: \
4852 case A##LB: \
4853 case A##ALB:
4854#define SIM_FUNC_H(A) \
4855 case A##H: \
4856 case A##AH: \
4857 case A##LH: \
4858 case A##ALH:
4859#define SIM_FUNC_w(A) \
4860 case A##_w: \
4861 case A##A_w: \
4862 case A##L_w: \
4863 case A##AL_w:
4864#define SIM_FUNC_x(A) \
4865 case A##_x: \
4866 case A##A_x: \
4867 case A##L_x: \
4868 case A##AL_x:
4869
4870 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4871 AtomicMemorySimpleHelper<uint8_t>(instr);
4872 break;
4873 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4874 AtomicMemorySimpleHelper<int8_t>(instr);
4875 break;
4876 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4877 AtomicMemorySimpleHelper<uint16_t>(instr);
4878 break;
4879 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4880 AtomicMemorySimpleHelper<int16_t>(instr);
4881 break;
4882 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4883 AtomicMemorySimpleHelper<uint32_t>(instr);
4884 break;
4885 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4886 AtomicMemorySimpleHelper<int32_t>(instr);
4887 break;
4888 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4889 AtomicMemorySimpleHelper<uint64_t>(instr);
4890 break;
4891 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4892 AtomicMemorySimpleHelper<int64_t>(instr);
4893 break;
4894 // clang-format on
4895
4896 case SWPB:
4897 case SWPAB:
4898 case SWPLB:
4899 case SWPALB:
4900 AtomicMemorySwapHelper<uint8_t>(instr);
4901 break;
4902 case SWPH:
4903 case SWPAH:
4904 case SWPLH:
4905 case SWPALH:
4906 AtomicMemorySwapHelper<uint16_t>(instr);
4907 break;
4908 case SWP_w:
4909 case SWPA_w:
4910 case SWPL_w:
4911 case SWPAL_w:
4912 AtomicMemorySwapHelper<uint32_t>(instr);
4913 break;
4914 case SWP_x:
4915 case SWPA_x:
4916 case SWPL_x:
4917 case SWPAL_x:
4918 AtomicMemorySwapHelper<uint64_t>(instr);
4919 break;
4920 case LDAPRB:
4921 LoadAcquireRCpcHelper<uint8_t>(instr);
4922 break;
4923 case LDAPRH:
4924 LoadAcquireRCpcHelper<uint16_t>(instr);
4925 break;
4926 case LDAPR_w:
4927 LoadAcquireRCpcHelper<uint32_t>(instr);
4928 break;
4929 case LDAPR_x:
4930 LoadAcquireRCpcHelper<uint64_t>(instr);
4931 break;
4932 }
4933}
4934
Alexandre Ramesd3832962016-07-04 15:03:43 +01004935
4936void Simulator::VisitLoadLiteral(const Instruction* instr) {
4937 unsigned rt = instr->GetRt();
4938 uint64_t address = instr->GetLiteralAddress<uint64_t>();
4939
4940 // Verify that the calculated address is available to the host.
4941 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4942
4943 switch (instr->Mask(LoadLiteralMask)) {
4944 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
4945 // print a more detailed log.
4946 case LDR_w_lit:
4947 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004948 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004949 break;
4950 case LDR_x_lit:
4951 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004952 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004953 break;
4954 case LDR_s_lit:
4955 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004956 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004957 break;
4958 case LDR_d_lit:
4959 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004960 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004961 break;
4962 case LDR_q_lit:
4963 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004964 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004965 break;
4966 case LDRSW_x_lit:
4967 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004968 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004969 break;
4970
4971 // Ignore prfm hint instructions.
4972 case PRFM_lit:
4973 break;
4974
4975 default:
4976 VIXL_UNREACHABLE();
4977 }
4978
4979 local_monitor_.MaybeClear();
4980}
4981
4982
4983uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
4984 int64_t offset,
4985 AddrMode addrmode) {
4986 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4987
4988 if ((addr_reg == 31) && ((address % 16) != 0)) {
4989 // When the base register is SP the stack pointer is required to be
4990 // quadword aligned prior to the address calculation and write-backs.
4991 // Misalignment will cause a stack alignment fault.
4992 VIXL_ALIGNMENT_EXCEPTION();
4993 }
4994
4995 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
4996 VIXL_ASSERT(offset != 0);
4997 // Only preindex should log the register update here. For Postindex, the
4998 // update will be printed automatically by LogWrittenRegisters _after_ the
4999 // memory access itself is logged.
5000 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5001 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5002 }
5003
5004 if ((addrmode == Offset) || (addrmode == PreIndex)) {
5005 address += offset;
5006 }
5007
5008 // Verify that the calculated address is available to the host.
5009 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5010
5011 return static_cast<uintptr_t>(address);
5012}
5013
5014
5015void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5016 MoveWideImmediateOp mov_op =
5017 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5018 int64_t new_xn_val = 0;
5019
5020 bool is_64_bits = instr->GetSixtyFourBits() == 1;
5021 // Shift is limited for W operations.
5022 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5023
5024 // Get the shifted immediate.
5025 int64_t shift = instr->GetShiftMoveWide() * 16;
5026 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5027 << shift;
5028
5029 // Compute the new value.
5030 switch (mov_op) {
5031 case MOVN_w:
5032 case MOVN_x: {
5033 new_xn_val = ~shifted_imm16;
5034 if (!is_64_bits) new_xn_val &= kWRegMask;
5035 break;
5036 }
5037 case MOVK_w:
5038 case MOVK_x: {
5039 unsigned reg_code = instr->GetRd();
5040 int64_t prev_xn_val =
5041 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5042 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5043 break;
5044 }
5045 case MOVZ_w:
5046 case MOVZ_x: {
5047 new_xn_val = shifted_imm16;
5048 break;
5049 }
5050 default:
5051 VIXL_UNREACHABLE();
5052 }
5053
5054 // Update the destination register.
5055 WriteXRegister(instr->GetRd(), new_xn_val);
5056}
5057
5058
5059void Simulator::VisitConditionalSelect(const Instruction* instr) {
5060 uint64_t new_val = ReadXRegister(instr->GetRn());
5061
5062 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5063 new_val = ReadXRegister(instr->GetRm());
5064 switch (instr->Mask(ConditionalSelectMask)) {
5065 case CSEL_w:
5066 case CSEL_x:
5067 break;
5068 case CSINC_w:
5069 case CSINC_x:
5070 new_val++;
5071 break;
5072 case CSINV_w:
5073 case CSINV_x:
5074 new_val = ~new_val;
5075 break;
5076 case CSNEG_w:
5077 case CSNEG_x:
5078 new_val = -new_val;
5079 break;
5080 default:
5081 VIXL_UNIMPLEMENTED();
5082 }
5083 }
5084 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5085 WriteRegister(reg_size, instr->GetRd(), new_val);
5086}
5087
5088
Jacob Bramleyca789742018-09-13 14:25:46 +01005089// clang-format off
5090#define PAUTH_MODES(V) \
5091 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
5092 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
5093 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
5094 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
5095 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
5096 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
5097 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
5098 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
5099// clang-format on
5100
Alexandre Ramesd3832962016-07-04 15:03:43 +01005101void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5102 unsigned dst = instr->GetRd();
5103 unsigned src = instr->GetRn();
5104
5105 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005106#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
5107 case PAC##SUFFIX: { \
5108 uint64_t ptr = ReadXRegister(dst); \
5109 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
5110 break; \
5111 } \
5112 case AUT##SUFFIX: { \
5113 uint64_t ptr = ReadXRegister(dst); \
5114 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
5115 break; \
5116 }
5117
5118 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
5119#undef DEFINE_PAUTH_FUNCS
5120
5121 case XPACI:
5122 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5123 break;
5124 case XPACD:
5125 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5126 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005127 case RBIT_w:
5128 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5129 break;
5130 case RBIT_x:
5131 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5132 break;
5133 case REV16_w:
5134 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5135 break;
5136 case REV16_x:
5137 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5138 break;
5139 case REV_w:
5140 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5141 break;
5142 case REV32_x:
5143 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5144 break;
5145 case REV_x:
5146 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5147 break;
5148 case CLZ_w:
5149 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5150 break;
5151 case CLZ_x:
5152 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5153 break;
5154 case CLS_w:
5155 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5156 break;
5157 case CLS_x:
5158 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5159 break;
5160 default:
5161 VIXL_UNIMPLEMENTED();
5162 }
5163}
5164
5165
5166uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5167 VIXL_ASSERT((n > 32) && (n <= 64));
5168 for (unsigned i = (n - 1); i >= 32; i--) {
5169 if (((data >> i) & 1) != 0) {
5170 uint64_t polysh32 = (uint64_t)poly << (i - 32);
5171 uint64_t mask = (UINT64_C(1) << i) - 1;
5172 data = ((data & mask) ^ polysh32);
5173 }
5174 }
5175 return data & 0xffffffff;
5176}
5177
5178
5179template <typename T>
5180uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5181 unsigned size = sizeof(val) * 8; // Number of bits in type T.
5182 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5183 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5184 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5185 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5186}
5187
5188
5189uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5190 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5191 // the CRC of each 32-bit word sequentially.
5192 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5193 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5194}
5195
5196
5197void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5198 Shift shift_op = NO_SHIFT;
5199 int64_t result = 0;
5200 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5201
5202 switch (instr->Mask(DataProcessing2SourceMask)) {
5203 case SDIV_w: {
5204 int32_t rn = ReadWRegister(instr->GetRn());
5205 int32_t rm = ReadWRegister(instr->GetRm());
5206 if ((rn == kWMinInt) && (rm == -1)) {
5207 result = kWMinInt;
5208 } else if (rm == 0) {
5209 // Division by zero can be trapped, but not on A-class processors.
5210 result = 0;
5211 } else {
5212 result = rn / rm;
5213 }
5214 break;
5215 }
5216 case SDIV_x: {
5217 int64_t rn = ReadXRegister(instr->GetRn());
5218 int64_t rm = ReadXRegister(instr->GetRm());
5219 if ((rn == kXMinInt) && (rm == -1)) {
5220 result = kXMinInt;
5221 } else if (rm == 0) {
5222 // Division by zero can be trapped, but not on A-class processors.
5223 result = 0;
5224 } else {
5225 result = rn / rm;
5226 }
5227 break;
5228 }
5229 case UDIV_w: {
5230 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5231 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5232 if (rm == 0) {
5233 // Division by zero can be trapped, but not on A-class processors.
5234 result = 0;
5235 } else {
5236 result = rn / rm;
5237 }
5238 break;
5239 }
5240 case UDIV_x: {
5241 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5242 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5243 if (rm == 0) {
5244 // Division by zero can be trapped, but not on A-class processors.
5245 result = 0;
5246 } else {
5247 result = rn / rm;
5248 }
5249 break;
5250 }
5251 case LSLV_w:
5252 case LSLV_x:
5253 shift_op = LSL;
5254 break;
5255 case LSRV_w:
5256 case LSRV_x:
5257 shift_op = LSR;
5258 break;
5259 case ASRV_w:
5260 case ASRV_x:
5261 shift_op = ASR;
5262 break;
5263 case RORV_w:
5264 case RORV_x:
5265 shift_op = ROR;
5266 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005267 case PACGA: {
5268 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5269 uint64_t src = static_cast<uint64_t>(
5270 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5271 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5272 result = code & 0xffffffff00000000;
5273 break;
5274 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005275 case CRC32B: {
5276 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5277 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5278 result = Crc32Checksum(acc, val, CRC32_POLY);
5279 break;
5280 }
5281 case CRC32H: {
5282 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5283 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5284 result = Crc32Checksum(acc, val, CRC32_POLY);
5285 break;
5286 }
5287 case CRC32W: {
5288 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5289 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5290 result = Crc32Checksum(acc, val, CRC32_POLY);
5291 break;
5292 }
5293 case CRC32X: {
5294 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5295 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5296 result = Crc32Checksum(acc, val, CRC32_POLY);
5297 reg_size = kWRegSize;
5298 break;
5299 }
5300 case CRC32CB: {
5301 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5302 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5303 result = Crc32Checksum(acc, val, CRC32C_POLY);
5304 break;
5305 }
5306 case CRC32CH: {
5307 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5308 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5309 result = Crc32Checksum(acc, val, CRC32C_POLY);
5310 break;
5311 }
5312 case CRC32CW: {
5313 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5314 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5315 result = Crc32Checksum(acc, val, CRC32C_POLY);
5316 break;
5317 }
5318 case CRC32CX: {
5319 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5320 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5321 result = Crc32Checksum(acc, val, CRC32C_POLY);
5322 reg_size = kWRegSize;
5323 break;
5324 }
5325 default:
5326 VIXL_UNIMPLEMENTED();
5327 }
5328
5329 if (shift_op != NO_SHIFT) {
5330 // Shift distance encoded in the least-significant five/six bits of the
5331 // register.
5332 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5333 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5334 result = ShiftOperand(reg_size,
5335 ReadRegister(reg_size, instr->GetRn()),
5336 shift_op,
5337 shift);
5338 }
5339 WriteRegister(reg_size, instr->GetRd(), result);
5340}
5341
5342
Alexandre Ramesd3832962016-07-04 15:03:43 +01005343void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5344 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5345
5346 uint64_t result = 0;
5347 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5348 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5349 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5350 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5351 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005352 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5353 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005354 switch (instr->Mask(DataProcessing3SourceMask)) {
5355 case MADD_w:
5356 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005357 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005358 break;
5359 case MSUB_w:
5360 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005361 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005362 break;
5363 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005364 result = ReadXRegister(instr->GetRa()) +
5365 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005366 break;
5367 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005368 result = ReadXRegister(instr->GetRa()) -
5369 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005370 break;
5371 case UMADDL_x:
5372 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5373 break;
5374 case UMSUBL_x:
5375 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5376 break;
5377 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005378 result =
5379 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5380 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005381 break;
5382 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005383 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5384 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005385 break;
5386 default:
5387 VIXL_UNIMPLEMENTED();
5388 }
5389 WriteRegister(reg_size, instr->GetRd(), result);
5390}
5391
5392
5393void Simulator::VisitBitfield(const Instruction* instr) {
5394 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5395 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005396 int R = instr->GetImmR();
5397 int S = instr->GetImmS();
5398 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005399 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005400 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005401 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005402 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005403 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005404 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005405 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005406 diff += reg_size;
5407 }
5408
5409 // inzero indicates if the extracted bitfield is inserted into the
5410 // destination register value or in zero.
5411 // If extend is true, extend the sign of the extracted bitfield.
5412 bool inzero = false;
5413 bool extend = false;
5414 switch (instr->Mask(BitfieldMask)) {
5415 case BFM_x:
5416 case BFM_w:
5417 break;
5418 case SBFM_x:
5419 case SBFM_w:
5420 inzero = true;
5421 extend = true;
5422 break;
5423 case UBFM_x:
5424 case UBFM_w:
5425 inzero = true;
5426 break;
5427 default:
5428 VIXL_UNIMPLEMENTED();
5429 }
5430
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005431 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5432 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005433 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005434 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005435 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005436 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5437 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005438
5439 // Merge sign extension, dest/zero and bitfield.
5440 result = signbits | (result & mask) | (dst & ~mask);
5441
5442 WriteRegister(reg_size, instr->GetRd(), result);
5443}
5444
5445
5446void Simulator::VisitExtract(const Instruction* instr) {
5447 unsigned lsb = instr->GetImmS();
5448 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5449 uint64_t low_res =
5450 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00005451 uint64_t high_res = (lsb == 0)
5452 ? 0
5453 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5454 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005455 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5456}
5457
5458
5459void Simulator::VisitFPImmediate(const Instruction* instr) {
5460 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005461 unsigned dest = instr->GetRd();
5462 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005463 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01005464 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01005465 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005466 case FMOV_s_imm:
5467 WriteSRegister(dest, instr->GetImmFP32());
5468 break;
5469 case FMOV_d_imm:
5470 WriteDRegister(dest, instr->GetImmFP64());
5471 break;
5472 default:
5473 VIXL_UNREACHABLE();
5474 }
5475}
5476
5477
5478void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5479 AssertSupportedFPCR();
5480
5481 unsigned dst = instr->GetRd();
5482 unsigned src = instr->GetRn();
5483
5484 FPRounding round = ReadRMode();
5485
5486 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005487 case FCVTAS_wh:
5488 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5489 break;
5490 case FCVTAS_xh:
5491 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5492 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005493 case FCVTAS_ws:
5494 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5495 break;
5496 case FCVTAS_xs:
5497 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5498 break;
5499 case FCVTAS_wd:
5500 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5501 break;
5502 case FCVTAS_xd:
5503 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5504 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005505 case FCVTAU_wh:
5506 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5507 break;
5508 case FCVTAU_xh:
5509 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5510 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005511 case FCVTAU_ws:
5512 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5513 break;
5514 case FCVTAU_xs:
5515 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5516 break;
5517 case FCVTAU_wd:
5518 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5519 break;
5520 case FCVTAU_xd:
5521 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5522 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005523 case FCVTMS_wh:
5524 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5525 break;
5526 case FCVTMS_xh:
5527 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5528 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005529 case FCVTMS_ws:
5530 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5531 break;
5532 case FCVTMS_xs:
5533 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5534 break;
5535 case FCVTMS_wd:
5536 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5537 break;
5538 case FCVTMS_xd:
5539 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5540 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005541 case FCVTMU_wh:
5542 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5543 break;
5544 case FCVTMU_xh:
5545 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5546 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005547 case FCVTMU_ws:
5548 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5549 break;
5550 case FCVTMU_xs:
5551 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5552 break;
5553 case FCVTMU_wd:
5554 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5555 break;
5556 case FCVTMU_xd:
5557 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5558 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005559 case FCVTPS_wh:
5560 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5561 break;
5562 case FCVTPS_xh:
5563 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5564 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005565 case FCVTPS_ws:
5566 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5567 break;
5568 case FCVTPS_xs:
5569 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5570 break;
5571 case FCVTPS_wd:
5572 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5573 break;
5574 case FCVTPS_xd:
5575 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5576 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005577 case FCVTPU_wh:
5578 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5579 break;
5580 case FCVTPU_xh:
5581 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5582 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005583 case FCVTPU_ws:
5584 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5585 break;
5586 case FCVTPU_xs:
5587 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5588 break;
5589 case FCVTPU_wd:
5590 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5591 break;
5592 case FCVTPU_xd:
5593 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5594 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005595 case FCVTNS_wh:
5596 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5597 break;
5598 case FCVTNS_xh:
5599 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5600 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005601 case FCVTNS_ws:
5602 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5603 break;
5604 case FCVTNS_xs:
5605 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5606 break;
5607 case FCVTNS_wd:
5608 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5609 break;
5610 case FCVTNS_xd:
5611 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5612 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005613 case FCVTNU_wh:
5614 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5615 break;
5616 case FCVTNU_xh:
5617 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5618 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005619 case FCVTNU_ws:
5620 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5621 break;
5622 case FCVTNU_xs:
5623 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5624 break;
5625 case FCVTNU_wd:
5626 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5627 break;
5628 case FCVTNU_xd:
5629 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5630 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005631 case FCVTZS_wh:
5632 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5633 break;
5634 case FCVTZS_xh:
5635 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5636 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005637 case FCVTZS_ws:
5638 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5639 break;
5640 case FCVTZS_xs:
5641 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5642 break;
5643 case FCVTZS_wd:
5644 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5645 break;
5646 case FCVTZS_xd:
5647 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5648 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005649 case FCVTZU_wh:
5650 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5651 break;
5652 case FCVTZU_xh:
5653 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5654 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005655 case FCVTZU_ws:
5656 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5657 break;
5658 case FCVTZU_xs:
5659 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5660 break;
5661 case FCVTZU_wd:
5662 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5663 break;
5664 case FCVTZU_xd:
5665 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5666 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005667 case FJCVTZS:
5668 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5669 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005670 case FMOV_hw:
5671 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5672 break;
5673 case FMOV_wh:
5674 WriteWRegister(dst, ReadHRegisterBits(src));
5675 break;
5676 case FMOV_xh:
5677 WriteXRegister(dst, ReadHRegisterBits(src));
5678 break;
5679 case FMOV_hx:
5680 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5681 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005682 case FMOV_ws:
5683 WriteWRegister(dst, ReadSRegisterBits(src));
5684 break;
5685 case FMOV_xd:
5686 WriteXRegister(dst, ReadDRegisterBits(src));
5687 break;
5688 case FMOV_sw:
5689 WriteSRegisterBits(dst, ReadWRegister(src));
5690 break;
5691 case FMOV_dx:
5692 WriteDRegisterBits(dst, ReadXRegister(src));
5693 break;
5694 case FMOV_d1_x:
5695 LogicVRegister(ReadVRegister(dst))
5696 .SetUint(kFormatD, 1, ReadXRegister(src));
5697 break;
5698 case FMOV_x_d1:
5699 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5700 break;
5701
5702 // A 32-bit input can be handled in the same way as a 64-bit input, since
5703 // the sign- or zero-extension will not affect the conversion.
5704 case SCVTF_dx:
5705 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5706 break;
5707 case SCVTF_dw:
5708 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5709 break;
5710 case UCVTF_dx:
5711 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5712 break;
5713 case UCVTF_dw: {
5714 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005715 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005716 break;
5717 }
5718 case SCVTF_sx:
5719 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5720 break;
5721 case SCVTF_sw:
5722 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5723 break;
5724 case UCVTF_sx:
5725 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5726 break;
5727 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01005728 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5729 break;
5730 }
5731 case SCVTF_hx:
5732 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5733 break;
5734 case SCVTF_hw:
5735 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5736 break;
5737 case UCVTF_hx:
5738 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5739 break;
5740 case UCVTF_hw: {
5741 WriteHRegister(dst,
5742 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005743 break;
5744 }
5745
5746 default:
5747 VIXL_UNREACHABLE();
5748 }
5749}
5750
5751
5752void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5753 AssertSupportedFPCR();
5754
5755 unsigned dst = instr->GetRd();
5756 unsigned src = instr->GetRn();
5757 int fbits = 64 - instr->GetFPScale();
5758
5759 FPRounding round = ReadRMode();
5760
5761 switch (instr->Mask(FPFixedPointConvertMask)) {
5762 // A 32-bit input can be handled in the same way as a 64-bit input, since
5763 // the sign- or zero-extension will not affect the conversion.
5764 case SCVTF_dx_fixed:
5765 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5766 break;
5767 case SCVTF_dw_fixed:
5768 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5769 break;
5770 case UCVTF_dx_fixed:
5771 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5772 break;
5773 case UCVTF_dw_fixed: {
5774 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005775 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005776 break;
5777 }
5778 case SCVTF_sx_fixed:
5779 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5780 break;
5781 case SCVTF_sw_fixed:
5782 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5783 break;
5784 case UCVTF_sx_fixed:
5785 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5786 break;
5787 case UCVTF_sw_fixed: {
5788 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005789 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5790 break;
5791 }
5792 case SCVTF_hx_fixed:
5793 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5794 break;
5795 case SCVTF_hw_fixed:
5796 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5797 break;
5798 case UCVTF_hx_fixed:
5799 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5800 break;
5801 case UCVTF_hw_fixed: {
5802 WriteHRegister(dst,
5803 UFixedToFloat16(ReadRegister<uint32_t>(src),
5804 fbits,
5805 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005806 break;
5807 }
5808 case FCVTZS_xd_fixed:
5809 WriteXRegister(dst,
5810 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5811 FPZero));
5812 break;
5813 case FCVTZS_wd_fixed:
5814 WriteWRegister(dst,
5815 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5816 FPZero));
5817 break;
5818 case FCVTZU_xd_fixed:
5819 WriteXRegister(dst,
5820 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5821 FPZero));
5822 break;
5823 case FCVTZU_wd_fixed:
5824 WriteWRegister(dst,
5825 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5826 FPZero));
5827 break;
5828 case FCVTZS_xs_fixed:
5829 WriteXRegister(dst,
5830 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5831 FPZero));
5832 break;
5833 case FCVTZS_ws_fixed:
5834 WriteWRegister(dst,
5835 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5836 FPZero));
5837 break;
5838 case FCVTZU_xs_fixed:
5839 WriteXRegister(dst,
5840 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5841 FPZero));
5842 break;
5843 case FCVTZU_ws_fixed:
5844 WriteWRegister(dst,
5845 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5846 FPZero));
5847 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005848 case FCVTZS_xh_fixed: {
5849 double output =
5850 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5851 WriteXRegister(dst, FPToInt64(output, FPZero));
5852 break;
5853 }
5854 case FCVTZS_wh_fixed: {
5855 double output =
5856 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5857 WriteWRegister(dst, FPToInt32(output, FPZero));
5858 break;
5859 }
5860 case FCVTZU_xh_fixed: {
5861 double output =
5862 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5863 WriteXRegister(dst, FPToUInt64(output, FPZero));
5864 break;
5865 }
5866 case FCVTZU_wh_fixed: {
5867 double output =
5868 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5869 WriteWRegister(dst, FPToUInt32(output, FPZero));
5870 break;
5871 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005872 default:
5873 VIXL_UNREACHABLE();
5874 }
5875}
5876
5877
5878void Simulator::VisitFPCompare(const Instruction* instr) {
5879 AssertSupportedFPCR();
5880
5881 FPTrapFlags trap = DisableTrap;
5882 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005883 case FCMPE_h:
5884 trap = EnableTrap;
5885 VIXL_FALLTHROUGH();
5886 case FCMP_h:
5887 FPCompare(ReadHRegister(instr->GetRn()),
5888 ReadHRegister(instr->GetRm()),
5889 trap);
5890 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005891 case FCMPE_s:
5892 trap = EnableTrap;
5893 VIXL_FALLTHROUGH();
5894 case FCMP_s:
5895 FPCompare(ReadSRegister(instr->GetRn()),
5896 ReadSRegister(instr->GetRm()),
5897 trap);
5898 break;
5899 case FCMPE_d:
5900 trap = EnableTrap;
5901 VIXL_FALLTHROUGH();
5902 case FCMP_d:
5903 FPCompare(ReadDRegister(instr->GetRn()),
5904 ReadDRegister(instr->GetRm()),
5905 trap);
5906 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005907 case FCMPE_h_zero:
5908 trap = EnableTrap;
5909 VIXL_FALLTHROUGH();
5910 case FCMP_h_zero:
5911 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5912 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005913 case FCMPE_s_zero:
5914 trap = EnableTrap;
5915 VIXL_FALLTHROUGH();
5916 case FCMP_s_zero:
5917 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
5918 break;
5919 case FCMPE_d_zero:
5920 trap = EnableTrap;
5921 VIXL_FALLTHROUGH();
5922 case FCMP_d_zero:
5923 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
5924 break;
5925 default:
5926 VIXL_UNIMPLEMENTED();
5927 }
5928}
5929
5930
5931void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
5932 AssertSupportedFPCR();
5933
5934 FPTrapFlags trap = DisableTrap;
5935 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005936 case FCCMPE_h:
5937 trap = EnableTrap;
5938 VIXL_FALLTHROUGH();
5939 case FCCMP_h:
5940 if (ConditionPassed(instr->GetCondition())) {
5941 FPCompare(ReadHRegister(instr->GetRn()),
5942 ReadHRegister(instr->GetRm()),
5943 trap);
5944 } else {
5945 ReadNzcv().SetFlags(instr->GetNzcv());
5946 LogSystemRegister(NZCV);
5947 }
5948 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005949 case FCCMPE_s:
5950 trap = EnableTrap;
5951 VIXL_FALLTHROUGH();
5952 case FCCMP_s:
5953 if (ConditionPassed(instr->GetCondition())) {
5954 FPCompare(ReadSRegister(instr->GetRn()),
5955 ReadSRegister(instr->GetRm()),
5956 trap);
5957 } else {
5958 ReadNzcv().SetFlags(instr->GetNzcv());
5959 LogSystemRegister(NZCV);
5960 }
5961 break;
5962 case FCCMPE_d:
5963 trap = EnableTrap;
5964 VIXL_FALLTHROUGH();
5965 case FCCMP_d:
5966 if (ConditionPassed(instr->GetCondition())) {
5967 FPCompare(ReadDRegister(instr->GetRn()),
5968 ReadDRegister(instr->GetRm()),
5969 trap);
5970 } else {
5971 ReadNzcv().SetFlags(instr->GetNzcv());
5972 LogSystemRegister(NZCV);
5973 }
5974 break;
5975 default:
5976 VIXL_UNIMPLEMENTED();
5977 }
5978}
5979
5980
5981void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
5982 AssertSupportedFPCR();
5983
5984 Instr selected;
5985 if (ConditionPassed(instr->GetCondition())) {
5986 selected = instr->GetRn();
5987 } else {
5988 selected = instr->GetRm();
5989 }
5990
5991 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005992 case FCSEL_h:
5993 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
5994 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005995 case FCSEL_s:
5996 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
5997 break;
5998 case FCSEL_d:
5999 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6000 break;
6001 default:
6002 VIXL_UNIMPLEMENTED();
6003 }
6004}
6005
6006
6007void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6008 AssertSupportedFPCR();
6009
6010 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006011 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006012 switch (instr->Mask(FPTypeMask)) {
6013 default:
6014 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6015 case FP64:
6016 vform = kFormatD;
6017 break;
6018 case FP32:
6019 vform = kFormatS;
6020 break;
6021 case FP16:
6022 vform = kFormatH;
6023 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006024 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006025
Alexandre Ramesd3832962016-07-04 15:03:43 +01006026 SimVRegister& rd = ReadVRegister(instr->GetRd());
6027 SimVRegister& rn = ReadVRegister(instr->GetRn());
6028 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006029 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006030
6031 unsigned fd = instr->GetRd();
6032 unsigned fn = instr->GetRn();
6033
6034 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01006035 case FMOV_h:
6036 WriteHRegister(fd, ReadHRegister(fn));
6037 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006038 case FMOV_s:
6039 WriteSRegister(fd, ReadSRegister(fn));
6040 return;
6041 case FMOV_d:
6042 WriteDRegister(fd, ReadDRegister(fn));
6043 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006044 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006045 case FABS_s:
6046 case FABS_d:
6047 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6048 // Explicitly log the register update whilst we have type information.
6049 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6050 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006051 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006052 case FNEG_s:
6053 case FNEG_d:
6054 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6055 // Explicitly log the register update whilst we have type information.
6056 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6057 return;
6058 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01006059 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006060 return;
6061 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01006062 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006063 return;
6064 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01006065 WriteHRegister(fd,
6066 Float16ToRawbits(
6067 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006068 return;
6069 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01006070 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006071 return;
6072 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01006073 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006074 return;
6075 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01006076 WriteHRegister(fd,
6077 Float16ToRawbits(
6078 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006079 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006080 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006081 case FSQRT_s:
6082 case FSQRT_d:
6083 fsqrt(vform, rd, rn);
6084 // Explicitly log the register update whilst we have type information.
6085 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6086 return;
TatWai Chong04471812019-03-19 14:29:00 -07006087 case FRINT32X_s:
6088 case FRINT32X_d:
6089 inexact_exception = true;
6090 frint_mode = kFrintToInt32;
6091 break; // Use FPCR rounding mode.
6092 case FRINT64X_s:
6093 case FRINT64X_d:
6094 inexact_exception = true;
6095 frint_mode = kFrintToInt64;
6096 break; // Use FPCR rounding mode.
6097 case FRINT32Z_s:
6098 case FRINT32Z_d:
6099 inexact_exception = true;
6100 frint_mode = kFrintToInt32;
6101 fpcr_rounding = FPZero;
6102 break;
6103 case FRINT64Z_s:
6104 case FRINT64Z_d:
6105 inexact_exception = true;
6106 frint_mode = kFrintToInt64;
6107 fpcr_rounding = FPZero;
6108 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006109 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006110 case FRINTI_s:
6111 case FRINTI_d:
6112 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01006113 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006114 case FRINTX_s:
6115 case FRINTX_d:
6116 inexact_exception = true;
6117 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006118 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006119 case FRINTA_s:
6120 case FRINTA_d:
6121 fpcr_rounding = FPTieAway;
6122 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006123 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006124 case FRINTM_s:
6125 case FRINTM_d:
6126 fpcr_rounding = FPNegativeInfinity;
6127 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006128 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006129 case FRINTN_s:
6130 case FRINTN_d:
6131 fpcr_rounding = FPTieEven;
6132 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006133 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006134 case FRINTP_s:
6135 case FRINTP_d:
6136 fpcr_rounding = FPPositiveInfinity;
6137 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006138 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006139 case FRINTZ_s:
6140 case FRINTZ_d:
6141 fpcr_rounding = FPZero;
6142 break;
6143 default:
6144 VIXL_UNIMPLEMENTED();
6145 }
6146
6147 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006148 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006149 // Explicitly log the register update whilst we have type information.
6150 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6151}
6152
6153
6154void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6155 AssertSupportedFPCR();
6156
Carey Williamsd8bb3572018-04-10 11:58:07 +01006157 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006158 switch (instr->Mask(FPTypeMask)) {
6159 default:
6160 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6161 case FP64:
6162 vform = kFormatD;
6163 break;
6164 case FP32:
6165 vform = kFormatS;
6166 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006167 case FP16:
6168 vform = kFormatH;
6169 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006170 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006171 SimVRegister& rd = ReadVRegister(instr->GetRd());
6172 SimVRegister& rn = ReadVRegister(instr->GetRn());
6173 SimVRegister& rm = ReadVRegister(instr->GetRm());
6174
6175 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006176 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006177 case FADD_s:
6178 case FADD_d:
6179 fadd(vform, rd, rn, rm);
6180 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006181 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006182 case FSUB_s:
6183 case FSUB_d:
6184 fsub(vform, rd, rn, rm);
6185 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006186 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006187 case FMUL_s:
6188 case FMUL_d:
6189 fmul(vform, rd, rn, rm);
6190 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006191 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006192 case FNMUL_s:
6193 case FNMUL_d:
6194 fnmul(vform, rd, rn, rm);
6195 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006196 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006197 case FDIV_s:
6198 case FDIV_d:
6199 fdiv(vform, rd, rn, rm);
6200 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006201 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006202 case FMAX_s:
6203 case FMAX_d:
6204 fmax(vform, rd, rn, rm);
6205 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006206 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006207 case FMIN_s:
6208 case FMIN_d:
6209 fmin(vform, rd, rn, rm);
6210 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006211 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006212 case FMAXNM_s:
6213 case FMAXNM_d:
6214 fmaxnm(vform, rd, rn, rm);
6215 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006216 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006217 case FMINNM_s:
6218 case FMINNM_d:
6219 fminnm(vform, rd, rn, rm);
6220 break;
6221 default:
6222 VIXL_UNREACHABLE();
6223 }
6224 // Explicitly log the register update whilst we have type information.
6225 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6226}
6227
6228
6229void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6230 AssertSupportedFPCR();
6231
6232 unsigned fd = instr->GetRd();
6233 unsigned fn = instr->GetRn();
6234 unsigned fm = instr->GetRm();
6235 unsigned fa = instr->GetRa();
6236
6237 switch (instr->Mask(FPDataProcessing3SourceMask)) {
6238 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01006239 case FMADD_h:
6240 WriteHRegister(fd,
6241 FPMulAdd(ReadHRegister(fa),
6242 ReadHRegister(fn),
6243 ReadHRegister(fm)));
6244 break;
6245 case FMSUB_h:
6246 WriteHRegister(fd,
6247 FPMulAdd(ReadHRegister(fa),
6248 -ReadHRegister(fn),
6249 ReadHRegister(fm)));
6250 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006251 case FMADD_s:
6252 WriteSRegister(fd,
6253 FPMulAdd(ReadSRegister(fa),
6254 ReadSRegister(fn),
6255 ReadSRegister(fm)));
6256 break;
6257 case FMSUB_s:
6258 WriteSRegister(fd,
6259 FPMulAdd(ReadSRegister(fa),
6260 -ReadSRegister(fn),
6261 ReadSRegister(fm)));
6262 break;
6263 case FMADD_d:
6264 WriteDRegister(fd,
6265 FPMulAdd(ReadDRegister(fa),
6266 ReadDRegister(fn),
6267 ReadDRegister(fm)));
6268 break;
6269 case FMSUB_d:
6270 WriteDRegister(fd,
6271 FPMulAdd(ReadDRegister(fa),
6272 -ReadDRegister(fn),
6273 ReadDRegister(fm)));
6274 break;
6275 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01006276 case FNMADD_h:
6277 WriteHRegister(fd,
6278 FPMulAdd(-ReadHRegister(fa),
6279 -ReadHRegister(fn),
6280 ReadHRegister(fm)));
6281 break;
6282 case FNMSUB_h:
6283 WriteHRegister(fd,
6284 FPMulAdd(-ReadHRegister(fa),
6285 ReadHRegister(fn),
6286 ReadHRegister(fm)));
6287 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006288 case FNMADD_s:
6289 WriteSRegister(fd,
6290 FPMulAdd(-ReadSRegister(fa),
6291 -ReadSRegister(fn),
6292 ReadSRegister(fm)));
6293 break;
6294 case FNMSUB_s:
6295 WriteSRegister(fd,
6296 FPMulAdd(-ReadSRegister(fa),
6297 ReadSRegister(fn),
6298 ReadSRegister(fm)));
6299 break;
6300 case FNMADD_d:
6301 WriteDRegister(fd,
6302 FPMulAdd(-ReadDRegister(fa),
6303 -ReadDRegister(fn),
6304 ReadDRegister(fm)));
6305 break;
6306 case FNMSUB_d:
6307 WriteDRegister(fd,
6308 FPMulAdd(-ReadDRegister(fa),
6309 ReadDRegister(fn),
6310 ReadDRegister(fm)));
6311 break;
6312 default:
6313 VIXL_UNIMPLEMENTED();
6314 }
6315}
6316
6317
6318bool Simulator::FPProcessNaNs(const Instruction* instr) {
6319 unsigned fd = instr->GetRd();
6320 unsigned fn = instr->GetRn();
6321 unsigned fm = instr->GetRm();
6322 bool done = false;
6323
6324 if (instr->Mask(FP64) == FP64) {
6325 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006326 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006327 WriteDRegister(fd, result);
6328 done = true;
6329 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006330 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006331 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006332 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006333 WriteSRegister(fd, result);
6334 done = true;
6335 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006336 } else {
6337 VIXL_ASSERT(instr->Mask(FP16) == FP16);
6338 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006339 }
6340
6341 return done;
6342}
6343
6344
6345void Simulator::SysOp_W(int op, int64_t val) {
6346 switch (op) {
6347 case IVAU:
6348 case CVAC:
6349 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01006350 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08006351 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006352 case CIVAC: {
6353 // Perform a dummy memory access to ensure that we have read access
6354 // to the specified address.
6355 volatile uint8_t y = Memory::Read<uint8_t>(val);
6356 USE(y);
6357 // TODO: Implement "case ZVA:".
6358 break;
6359 }
6360 default:
6361 VIXL_UNIMPLEMENTED();
6362 }
6363}
6364
6365
Jacob Bramleyca789742018-09-13 14:25:46 +01006366// clang-format off
6367#define PAUTH_SYSTEM_MODES(V) \
6368 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
6369 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
6370 V(AZ, 30, 0x00000000, kPACKeyIA) \
6371 V(BZ, 30, 0x00000000, kPACKeyIB) \
6372 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6373 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6374// clang-format on
6375
6376
Alexandre Ramesd3832962016-07-04 15:03:43 +01006377void Simulator::VisitSystem(const Instruction* instr) {
6378 // Some system instructions hijack their Op and Cp fields to represent a
6379 // range of immediates instead of indicating a different instruction. This
6380 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01006381 if (instr->GetInstructionBits() == XPACLRI) {
6382 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00006383 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6384 switch (instr->Mask(SystemPStateMask)) {
6385 case CFINV:
6386 ReadNzcv().SetC(!ReadC());
6387 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00006388 case AXFLAG:
6389 ReadNzcv().SetN(0);
6390 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6391 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6392 ReadNzcv().SetV(0);
6393 break;
6394 case XAFLAG: {
6395 // Can't set the flags in place due to the logical dependencies.
6396 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6397 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6398 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6399 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6400 ReadNzcv().SetN(n);
6401 ReadNzcv().SetZ(z);
6402 ReadNzcv().SetC(c);
6403 ReadNzcv().SetV(v);
6404 break;
6405 }
Alexander Gilday2487f142018-11-05 13:07:27 +00006406 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006407 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006408 // Check BType allows PACI[AB]SP instructions.
6409 if (PcIsInGuardedPage()) {
6410 Instr i = instr->Mask(SystemPAuthMask);
6411 if ((i == PACIASP) || (i == PACIBSP)) {
6412 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006413 case BranchFromGuardedNotToIP:
6414 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6415 // assume here to be zero. This allows execution of PACI[AB]SP when
6416 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00006417 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006418 case BranchFromUnguardedOrToIP:
6419 case BranchAndLink:
6420 break;
6421 }
6422 }
6423 }
6424
Jacob Bramleyca789742018-09-13 14:25:46 +01006425 switch (instr->Mask(SystemPAuthMask)) {
6426#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
6427 case PACI##SUFFIX: \
6428 WriteXRegister(DST, \
6429 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6430 break; \
6431 case AUTI##SUFFIX: \
6432 WriteXRegister(DST, \
6433 AuthPAC(ReadXRegister(DST), \
6434 MOD, \
6435 KEY, \
6436 kInstructionPointer)); \
6437 break;
6438
6439 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6440#undef DEFINE_PAUTH_FUNCS
6441 }
6442 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6443 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006444 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6445 switch (instr->Mask(SystemExclusiveMonitorMask)) {
6446 case CLREX: {
6447 PrintExclusiveAccessWarning();
6448 ClearLocalMonitor();
6449 break;
6450 }
6451 }
6452 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6453 switch (instr->Mask(SystemSysRegMask)) {
6454 case MRS: {
6455 switch (instr->GetImmSystemRegister()) {
6456 case NZCV:
6457 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6458 break;
6459 case FPCR:
6460 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6461 break;
TatWai Chong04edf682018-12-27 16:01:02 -08006462 case RNDR:
6463 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00006464 uint64_t high = jrand48(rand_state_);
6465 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08006466 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6467 WriteXRegister(instr->GetRt(), rand_num);
6468 // Simulate successful random number generation.
6469 // TODO: Return failure occasionally as a random number cannot be
6470 // returned in a period of time.
6471 ReadNzcv().SetRawValue(NoFlag);
6472 LogSystemRegister(NZCV);
6473 break;
6474 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006475 default:
6476 VIXL_UNIMPLEMENTED();
6477 }
6478 break;
6479 }
6480 case MSR: {
6481 switch (instr->GetImmSystemRegister()) {
6482 case NZCV:
6483 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6484 LogSystemRegister(NZCV);
6485 break;
6486 case FPCR:
6487 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6488 LogSystemRegister(FPCR);
6489 break;
6490 default:
6491 VIXL_UNIMPLEMENTED();
6492 }
6493 break;
6494 }
6495 }
6496 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6497 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6498 switch (instr->GetImmHint()) {
6499 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01006500 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00006501 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006502 case BTI_jc:
6503 break;
6504 case BTI:
6505 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6506 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6507 }
6508 break;
6509 case BTI_c:
6510 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6511 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6512 }
6513 break;
6514 case BTI_j:
6515 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6516 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6517 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006518 break;
6519 default:
6520 VIXL_UNIMPLEMENTED();
6521 }
6522 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6523 __sync_synchronize();
6524 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6525 switch (instr->Mask(SystemSysMask)) {
6526 case SYS:
6527 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6528 break;
6529 default:
6530 VIXL_UNIMPLEMENTED();
6531 }
6532 } else {
6533 VIXL_UNIMPLEMENTED();
6534 }
6535}
6536
6537
6538void Simulator::VisitException(const Instruction* instr) {
6539 switch (instr->Mask(ExceptionMask)) {
6540 case HLT:
6541 switch (instr->GetImmException()) {
6542 case kUnreachableOpcode:
6543 DoUnreachable(instr);
6544 return;
6545 case kTraceOpcode:
6546 DoTrace(instr);
6547 return;
6548 case kLogOpcode:
6549 DoLog(instr);
6550 return;
6551 case kPrintfOpcode:
6552 DoPrintf(instr);
6553 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01006554 case kRuntimeCallOpcode:
6555 DoRuntimeCall(instr);
6556 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01006557 case kSetCPUFeaturesOpcode:
6558 case kEnableCPUFeaturesOpcode:
6559 case kDisableCPUFeaturesOpcode:
6560 DoConfigureCPUFeatures(instr);
6561 return;
6562 case kSaveCPUFeaturesOpcode:
6563 DoSaveCPUFeatures(instr);
6564 return;
6565 case kRestoreCPUFeaturesOpcode:
6566 DoRestoreCPUFeatures(instr);
6567 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006568 default:
6569 HostBreakpoint();
6570 return;
6571 }
6572 case BRK:
6573 HostBreakpoint();
6574 return;
6575 default:
6576 VIXL_UNIMPLEMENTED();
6577 }
6578}
6579
6580
6581void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6582 VisitUnimplemented(instr);
6583}
6584
6585
6586void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6587 VisitUnimplemented(instr);
6588}
6589
6590
6591void Simulator::VisitCryptoAES(const Instruction* instr) {
6592 VisitUnimplemented(instr);
6593}
6594
6595
6596void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6597 NEONFormatDecoder nfd(instr);
6598 VectorFormat vf = nfd.GetVectorFormat();
6599
6600 static const NEONFormatMap map_lp =
6601 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6602 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6603
6604 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6605 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6606
6607 static const NEONFormatMap map_fcvtn = {{22, 30},
6608 {NF_4H, NF_8H, NF_2S, NF_4S}};
6609 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6610
6611 SimVRegister& rd = ReadVRegister(instr->GetRd());
6612 SimVRegister& rn = ReadVRegister(instr->GetRn());
6613
6614 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6615 // These instructions all use a two bit size field, except NOT and RBIT,
6616 // which use the field to encode the operation.
6617 switch (instr->Mask(NEON2RegMiscMask)) {
6618 case NEON_REV64:
6619 rev64(vf, rd, rn);
6620 break;
6621 case NEON_REV32:
6622 rev32(vf, rd, rn);
6623 break;
6624 case NEON_REV16:
6625 rev16(vf, rd, rn);
6626 break;
6627 case NEON_SUQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006628 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006629 break;
6630 case NEON_USQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006631 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006632 break;
6633 case NEON_CLS:
6634 cls(vf, rd, rn);
6635 break;
6636 case NEON_CLZ:
6637 clz(vf, rd, rn);
6638 break;
6639 case NEON_CNT:
6640 cnt(vf, rd, rn);
6641 break;
6642 case NEON_SQABS:
6643 abs(vf, rd, rn).SignedSaturate(vf);
6644 break;
6645 case NEON_SQNEG:
6646 neg(vf, rd, rn).SignedSaturate(vf);
6647 break;
6648 case NEON_CMGT_zero:
6649 cmp(vf, rd, rn, 0, gt);
6650 break;
6651 case NEON_CMGE_zero:
6652 cmp(vf, rd, rn, 0, ge);
6653 break;
6654 case NEON_CMEQ_zero:
6655 cmp(vf, rd, rn, 0, eq);
6656 break;
6657 case NEON_CMLE_zero:
6658 cmp(vf, rd, rn, 0, le);
6659 break;
6660 case NEON_CMLT_zero:
6661 cmp(vf, rd, rn, 0, lt);
6662 break;
6663 case NEON_ABS:
6664 abs(vf, rd, rn);
6665 break;
6666 case NEON_NEG:
6667 neg(vf, rd, rn);
6668 break;
6669 case NEON_SADDLP:
6670 saddlp(vf_lp, rd, rn);
6671 break;
6672 case NEON_UADDLP:
6673 uaddlp(vf_lp, rd, rn);
6674 break;
6675 case NEON_SADALP:
6676 sadalp(vf_lp, rd, rn);
6677 break;
6678 case NEON_UADALP:
6679 uadalp(vf_lp, rd, rn);
6680 break;
6681 case NEON_RBIT_NOT:
6682 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6683 switch (instr->GetFPType()) {
6684 case 0:
6685 not_(vf, rd, rn);
6686 break;
6687 case 1:
6688 rbit(vf, rd, rn);
6689 break;
6690 default:
6691 VIXL_UNIMPLEMENTED();
6692 }
6693 break;
6694 }
6695 } else {
6696 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6697 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6698 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006699 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006700
6701 // These instructions all use a one bit size field, except XTN, SQXTUN,
6702 // SHLL, SQXTN and UQXTN, which use a two bit size field.
6703 switch (instr->Mask(NEON2RegMiscFPMask)) {
6704 case NEON_FABS:
6705 fabs_(fpf, rd, rn);
6706 return;
6707 case NEON_FNEG:
6708 fneg(fpf, rd, rn);
6709 return;
6710 case NEON_FSQRT:
6711 fsqrt(fpf, rd, rn);
6712 return;
6713 case NEON_FCVTL:
6714 if (instr->Mask(NEON_Q)) {
6715 fcvtl2(vf_fcvtl, rd, rn);
6716 } else {
6717 fcvtl(vf_fcvtl, rd, rn);
6718 }
6719 return;
6720 case NEON_FCVTN:
6721 if (instr->Mask(NEON_Q)) {
6722 fcvtn2(vf_fcvtn, rd, rn);
6723 } else {
6724 fcvtn(vf_fcvtn, rd, rn);
6725 }
6726 return;
6727 case NEON_FCVTXN:
6728 if (instr->Mask(NEON_Q)) {
6729 fcvtxn2(vf_fcvtn, rd, rn);
6730 } else {
6731 fcvtxn(vf_fcvtn, rd, rn);
6732 }
6733 return;
6734
6735 // The following instructions break from the switch statement, rather
6736 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07006737 case NEON_FRINT32X:
6738 inexact_exception = true;
6739 frint_mode = kFrintToInt32;
6740 break; // Use FPCR rounding mode.
6741 case NEON_FRINT32Z:
6742 inexact_exception = true;
6743 frint_mode = kFrintToInt32;
6744 fpcr_rounding = FPZero;
6745 break;
6746 case NEON_FRINT64X:
6747 inexact_exception = true;
6748 frint_mode = kFrintToInt64;
6749 break; // Use FPCR rounding mode.
6750 case NEON_FRINT64Z:
6751 inexact_exception = true;
6752 frint_mode = kFrintToInt64;
6753 fpcr_rounding = FPZero;
6754 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006755 case NEON_FRINTI:
6756 break; // Use FPCR rounding mode.
6757 case NEON_FRINTX:
6758 inexact_exception = true;
6759 break;
6760 case NEON_FRINTA:
6761 fpcr_rounding = FPTieAway;
6762 break;
6763 case NEON_FRINTM:
6764 fpcr_rounding = FPNegativeInfinity;
6765 break;
6766 case NEON_FRINTN:
6767 fpcr_rounding = FPTieEven;
6768 break;
6769 case NEON_FRINTP:
6770 fpcr_rounding = FPPositiveInfinity;
6771 break;
6772 case NEON_FRINTZ:
6773 fpcr_rounding = FPZero;
6774 break;
6775
6776 case NEON_FCVTNS:
6777 fcvts(fpf, rd, rn, FPTieEven);
6778 return;
6779 case NEON_FCVTNU:
6780 fcvtu(fpf, rd, rn, FPTieEven);
6781 return;
6782 case NEON_FCVTPS:
6783 fcvts(fpf, rd, rn, FPPositiveInfinity);
6784 return;
6785 case NEON_FCVTPU:
6786 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6787 return;
6788 case NEON_FCVTMS:
6789 fcvts(fpf, rd, rn, FPNegativeInfinity);
6790 return;
6791 case NEON_FCVTMU:
6792 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6793 return;
6794 case NEON_FCVTZS:
6795 fcvts(fpf, rd, rn, FPZero);
6796 return;
6797 case NEON_FCVTZU:
6798 fcvtu(fpf, rd, rn, FPZero);
6799 return;
6800 case NEON_FCVTAS:
6801 fcvts(fpf, rd, rn, FPTieAway);
6802 return;
6803 case NEON_FCVTAU:
6804 fcvtu(fpf, rd, rn, FPTieAway);
6805 return;
6806 case NEON_SCVTF:
6807 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6808 return;
6809 case NEON_UCVTF:
6810 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6811 return;
6812 case NEON_URSQRTE:
6813 ursqrte(fpf, rd, rn);
6814 return;
6815 case NEON_URECPE:
6816 urecpe(fpf, rd, rn);
6817 return;
6818 case NEON_FRSQRTE:
6819 frsqrte(fpf, rd, rn);
6820 return;
6821 case NEON_FRECPE:
6822 frecpe(fpf, rd, rn, fpcr_rounding);
6823 return;
6824 case NEON_FCMGT_zero:
6825 fcmp_zero(fpf, rd, rn, gt);
6826 return;
6827 case NEON_FCMGE_zero:
6828 fcmp_zero(fpf, rd, rn, ge);
6829 return;
6830 case NEON_FCMEQ_zero:
6831 fcmp_zero(fpf, rd, rn, eq);
6832 return;
6833 case NEON_FCMLE_zero:
6834 fcmp_zero(fpf, rd, rn, le);
6835 return;
6836 case NEON_FCMLT_zero:
6837 fcmp_zero(fpf, rd, rn, lt);
6838 return;
6839 default:
6840 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6841 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6842 switch (instr->Mask(NEON2RegMiscMask)) {
6843 case NEON_XTN:
6844 xtn(vf, rd, rn);
6845 return;
6846 case NEON_SQXTN:
6847 sqxtn(vf, rd, rn);
6848 return;
6849 case NEON_UQXTN:
6850 uqxtn(vf, rd, rn);
6851 return;
6852 case NEON_SQXTUN:
6853 sqxtun(vf, rd, rn);
6854 return;
6855 case NEON_SHLL:
6856 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6857 if (instr->Mask(NEON_Q)) {
6858 shll2(vf, rd, rn);
6859 } else {
6860 shll(vf, rd, rn);
6861 }
6862 return;
6863 default:
6864 VIXL_UNIMPLEMENTED();
6865 }
6866 } else {
6867 VIXL_UNIMPLEMENTED();
6868 }
6869 }
6870
6871 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006872 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006873 }
6874}
6875
6876
Jacob Bramleyca789742018-09-13 14:25:46 +01006877void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6878 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6879 NEONFormatDecoder nfd(instr);
6880 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6881
6882 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6883
6884 SimVRegister& rd = ReadVRegister(instr->GetRd());
6885 SimVRegister& rn = ReadVRegister(instr->GetRn());
6886
6887 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6888 case NEON_SCVTF_H:
6889 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6890 return;
6891 case NEON_UCVTF_H:
6892 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6893 return;
6894 case NEON_FCVTNS_H:
6895 fcvts(fpf, rd, rn, FPTieEven);
6896 return;
6897 case NEON_FCVTNU_H:
6898 fcvtu(fpf, rd, rn, FPTieEven);
6899 return;
6900 case NEON_FCVTPS_H:
6901 fcvts(fpf, rd, rn, FPPositiveInfinity);
6902 return;
6903 case NEON_FCVTPU_H:
6904 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6905 return;
6906 case NEON_FCVTMS_H:
6907 fcvts(fpf, rd, rn, FPNegativeInfinity);
6908 return;
6909 case NEON_FCVTMU_H:
6910 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6911 return;
6912 case NEON_FCVTZS_H:
6913 fcvts(fpf, rd, rn, FPZero);
6914 return;
6915 case NEON_FCVTZU_H:
6916 fcvtu(fpf, rd, rn, FPZero);
6917 return;
6918 case NEON_FCVTAS_H:
6919 fcvts(fpf, rd, rn, FPTieAway);
6920 return;
6921 case NEON_FCVTAU_H:
6922 fcvtu(fpf, rd, rn, FPTieAway);
6923 return;
6924 case NEON_FRINTI_H:
6925 frint(fpf, rd, rn, fpcr_rounding, false);
6926 return;
6927 case NEON_FRINTX_H:
6928 frint(fpf, rd, rn, fpcr_rounding, true);
6929 return;
6930 case NEON_FRINTA_H:
6931 frint(fpf, rd, rn, FPTieAway, false);
6932 return;
6933 case NEON_FRINTM_H:
6934 frint(fpf, rd, rn, FPNegativeInfinity, false);
6935 return;
6936 case NEON_FRINTN_H:
6937 frint(fpf, rd, rn, FPTieEven, false);
6938 return;
6939 case NEON_FRINTP_H:
6940 frint(fpf, rd, rn, FPPositiveInfinity, false);
6941 return;
6942 case NEON_FRINTZ_H:
6943 frint(fpf, rd, rn, FPZero, false);
6944 return;
6945 case NEON_FABS_H:
6946 fabs_(fpf, rd, rn);
6947 return;
6948 case NEON_FNEG_H:
6949 fneg(fpf, rd, rn);
6950 return;
6951 case NEON_FSQRT_H:
6952 fsqrt(fpf, rd, rn);
6953 return;
6954 case NEON_FRSQRTE_H:
6955 frsqrte(fpf, rd, rn);
6956 return;
6957 case NEON_FRECPE_H:
6958 frecpe(fpf, rd, rn, fpcr_rounding);
6959 return;
6960 case NEON_FCMGT_H_zero:
6961 fcmp_zero(fpf, rd, rn, gt);
6962 return;
6963 case NEON_FCMGE_H_zero:
6964 fcmp_zero(fpf, rd, rn, ge);
6965 return;
6966 case NEON_FCMEQ_H_zero:
6967 fcmp_zero(fpf, rd, rn, eq);
6968 return;
6969 case NEON_FCMLE_H_zero:
6970 fcmp_zero(fpf, rd, rn, le);
6971 return;
6972 case NEON_FCMLT_H_zero:
6973 fcmp_zero(fpf, rd, rn, lt);
6974 return;
6975 default:
6976 VIXL_UNIMPLEMENTED();
6977 return;
6978 }
6979}
6980
6981
Alexandre Ramesd3832962016-07-04 15:03:43 +01006982void Simulator::VisitNEON3Same(const Instruction* instr) {
6983 NEONFormatDecoder nfd(instr);
6984 SimVRegister& rd = ReadVRegister(instr->GetRd());
6985 SimVRegister& rn = ReadVRegister(instr->GetRn());
6986 SimVRegister& rm = ReadVRegister(instr->GetRm());
6987
6988 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
6989 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6990 switch (instr->Mask(NEON3SameLogicalMask)) {
6991 case NEON_AND:
6992 and_(vf, rd, rn, rm);
6993 break;
6994 case NEON_ORR:
6995 orr(vf, rd, rn, rm);
6996 break;
6997 case NEON_ORN:
6998 orn(vf, rd, rn, rm);
6999 break;
7000 case NEON_EOR:
7001 eor(vf, rd, rn, rm);
7002 break;
7003 case NEON_BIC:
7004 bic(vf, rd, rn, rm);
7005 break;
7006 case NEON_BIF:
7007 bif(vf, rd, rn, rm);
7008 break;
7009 case NEON_BIT:
7010 bit(vf, rd, rn, rm);
7011 break;
7012 case NEON_BSL:
Martyn Capewellb1b95782020-10-23 15:59:49 +01007013 bsl(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007014 break;
7015 default:
7016 VIXL_UNIMPLEMENTED();
7017 }
7018 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7019 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7020 switch (instr->Mask(NEON3SameFPMask)) {
7021 case NEON_FADD:
7022 fadd(vf, rd, rn, rm);
7023 break;
7024 case NEON_FSUB:
7025 fsub(vf, rd, rn, rm);
7026 break;
7027 case NEON_FMUL:
7028 fmul(vf, rd, rn, rm);
7029 break;
7030 case NEON_FDIV:
7031 fdiv(vf, rd, rn, rm);
7032 break;
7033 case NEON_FMAX:
7034 fmax(vf, rd, rn, rm);
7035 break;
7036 case NEON_FMIN:
7037 fmin(vf, rd, rn, rm);
7038 break;
7039 case NEON_FMAXNM:
7040 fmaxnm(vf, rd, rn, rm);
7041 break;
7042 case NEON_FMINNM:
7043 fminnm(vf, rd, rn, rm);
7044 break;
7045 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007046 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007047 break;
7048 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007049 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007050 break;
7051 case NEON_FMULX:
7052 fmulx(vf, rd, rn, rm);
7053 break;
7054 case NEON_FACGE:
7055 fabscmp(vf, rd, rn, rm, ge);
7056 break;
7057 case NEON_FACGT:
7058 fabscmp(vf, rd, rn, rm, gt);
7059 break;
7060 case NEON_FCMEQ:
7061 fcmp(vf, rd, rn, rm, eq);
7062 break;
7063 case NEON_FCMGE:
7064 fcmp(vf, rd, rn, rm, ge);
7065 break;
7066 case NEON_FCMGT:
7067 fcmp(vf, rd, rn, rm, gt);
7068 break;
7069 case NEON_FRECPS:
7070 frecps(vf, rd, rn, rm);
7071 break;
7072 case NEON_FRSQRTS:
7073 frsqrts(vf, rd, rn, rm);
7074 break;
7075 case NEON_FABD:
7076 fabd(vf, rd, rn, rm);
7077 break;
7078 case NEON_FADDP:
7079 faddp(vf, rd, rn, rm);
7080 break;
7081 case NEON_FMAXP:
7082 fmaxp(vf, rd, rn, rm);
7083 break;
7084 case NEON_FMAXNMP:
7085 fmaxnmp(vf, rd, rn, rm);
7086 break;
7087 case NEON_FMINP:
7088 fminp(vf, rd, rn, rm);
7089 break;
7090 case NEON_FMINNMP:
7091 fminnmp(vf, rd, rn, rm);
7092 break;
7093 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007094 // FMLAL{2} and FMLSL{2} have special-case encodings.
7095 switch (instr->Mask(NEON3SameFHMMask)) {
7096 case NEON_FMLAL:
7097 fmlal(vf, rd, rn, rm);
7098 break;
7099 case NEON_FMLAL2:
7100 fmlal2(vf, rd, rn, rm);
7101 break;
7102 case NEON_FMLSL:
7103 fmlsl(vf, rd, rn, rm);
7104 break;
7105 case NEON_FMLSL2:
7106 fmlsl2(vf, rd, rn, rm);
7107 break;
7108 default:
7109 VIXL_UNIMPLEMENTED();
7110 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007111 }
7112 } else {
7113 VectorFormat vf = nfd.GetVectorFormat();
7114 switch (instr->Mask(NEON3SameMask)) {
7115 case NEON_ADD:
7116 add(vf, rd, rn, rm);
7117 break;
7118 case NEON_ADDP:
7119 addp(vf, rd, rn, rm);
7120 break;
7121 case NEON_CMEQ:
7122 cmp(vf, rd, rn, rm, eq);
7123 break;
7124 case NEON_CMGE:
7125 cmp(vf, rd, rn, rm, ge);
7126 break;
7127 case NEON_CMGT:
7128 cmp(vf, rd, rn, rm, gt);
7129 break;
7130 case NEON_CMHI:
7131 cmp(vf, rd, rn, rm, hi);
7132 break;
7133 case NEON_CMHS:
7134 cmp(vf, rd, rn, rm, hs);
7135 break;
7136 case NEON_CMTST:
7137 cmptst(vf, rd, rn, rm);
7138 break;
7139 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01007140 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007141 break;
7142 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01007143 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007144 break;
7145 case NEON_MUL:
7146 mul(vf, rd, rn, rm);
7147 break;
7148 case NEON_PMUL:
7149 pmul(vf, rd, rn, rm);
7150 break;
7151 case NEON_SMAX:
7152 smax(vf, rd, rn, rm);
7153 break;
7154 case NEON_SMAXP:
7155 smaxp(vf, rd, rn, rm);
7156 break;
7157 case NEON_SMIN:
7158 smin(vf, rd, rn, rm);
7159 break;
7160 case NEON_SMINP:
7161 sminp(vf, rd, rn, rm);
7162 break;
7163 case NEON_SUB:
7164 sub(vf, rd, rn, rm);
7165 break;
7166 case NEON_UMAX:
7167 umax(vf, rd, rn, rm);
7168 break;
7169 case NEON_UMAXP:
7170 umaxp(vf, rd, rn, rm);
7171 break;
7172 case NEON_UMIN:
7173 umin(vf, rd, rn, rm);
7174 break;
7175 case NEON_UMINP:
7176 uminp(vf, rd, rn, rm);
7177 break;
7178 case NEON_SSHL:
7179 sshl(vf, rd, rn, rm);
7180 break;
7181 case NEON_USHL:
7182 ushl(vf, rd, rn, rm);
7183 break;
7184 case NEON_SABD:
7185 absdiff(vf, rd, rn, rm, true);
7186 break;
7187 case NEON_UABD:
7188 absdiff(vf, rd, rn, rm, false);
7189 break;
7190 case NEON_SABA:
7191 saba(vf, rd, rn, rm);
7192 break;
7193 case NEON_UABA:
7194 uaba(vf, rd, rn, rm);
7195 break;
7196 case NEON_UQADD:
7197 add(vf, rd, rn, rm).UnsignedSaturate(vf);
7198 break;
7199 case NEON_SQADD:
7200 add(vf, rd, rn, rm).SignedSaturate(vf);
7201 break;
7202 case NEON_UQSUB:
7203 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7204 break;
7205 case NEON_SQSUB:
7206 sub(vf, rd, rn, rm).SignedSaturate(vf);
7207 break;
7208 case NEON_SQDMULH:
7209 sqdmulh(vf, rd, rn, rm);
7210 break;
7211 case NEON_SQRDMULH:
7212 sqrdmulh(vf, rd, rn, rm);
7213 break;
7214 case NEON_UQSHL:
7215 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7216 break;
7217 case NEON_SQSHL:
7218 sshl(vf, rd, rn, rm).SignedSaturate(vf);
7219 break;
7220 case NEON_URSHL:
7221 ushl(vf, rd, rn, rm).Round(vf);
7222 break;
7223 case NEON_SRSHL:
7224 sshl(vf, rd, rn, rm).Round(vf);
7225 break;
7226 case NEON_UQRSHL:
7227 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7228 break;
7229 case NEON_SQRSHL:
7230 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7231 break;
7232 case NEON_UHADD:
7233 add(vf, rd, rn, rm).Uhalve(vf);
7234 break;
7235 case NEON_URHADD:
7236 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7237 break;
7238 case NEON_SHADD:
7239 add(vf, rd, rn, rm).Halve(vf);
7240 break;
7241 case NEON_SRHADD:
7242 add(vf, rd, rn, rm).Halve(vf).Round(vf);
7243 break;
7244 case NEON_UHSUB:
7245 sub(vf, rd, rn, rm).Uhalve(vf);
7246 break;
7247 case NEON_SHSUB:
7248 sub(vf, rd, rn, rm).Halve(vf);
7249 break;
7250 default:
7251 VIXL_UNIMPLEMENTED();
7252 }
7253 }
7254}
7255
7256
Jacob Bramleyca789742018-09-13 14:25:46 +01007257void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7258 NEONFormatDecoder nfd(instr);
7259 SimVRegister& rd = ReadVRegister(instr->GetRd());
7260 SimVRegister& rn = ReadVRegister(instr->GetRn());
7261 SimVRegister& rm = ReadVRegister(instr->GetRm());
7262
7263 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7264 switch (instr->Mask(NEON3SameFP16Mask)) {
7265#define SIM_FUNC(A, B) \
7266 case NEON_##A##_H: \
7267 B(vf, rd, rn, rm); \
7268 break;
7269 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007270 SIM_FUNC(FADD, fadd);
7271 SIM_FUNC(FMULX, fmulx);
7272 SIM_FUNC(FMAX, fmax);
7273 SIM_FUNC(FRECPS, frecps);
7274 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007275 SIM_FUNC(FSUB, fsub);
7276 SIM_FUNC(FMIN, fmin);
7277 SIM_FUNC(FRSQRTS, frsqrts);
7278 SIM_FUNC(FMAXNMP, fmaxnmp);
7279 SIM_FUNC(FADDP, faddp);
7280 SIM_FUNC(FMUL, fmul);
7281 SIM_FUNC(FMAXP, fmaxp);
7282 SIM_FUNC(FDIV, fdiv);
7283 SIM_FUNC(FMINNMP, fminnmp);
7284 SIM_FUNC(FABD, fabd);
7285 SIM_FUNC(FMINP, fminp);
7286#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08007287 case NEON_FMLA_H:
7288 fmla(vf, rd, rd, rn, rm);
7289 break;
7290 case NEON_FMLS_H:
7291 fmls(vf, rd, rd, rn, rm);
7292 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007293 case NEON_FCMEQ_H:
7294 fcmp(vf, rd, rn, rm, eq);
7295 break;
7296 case NEON_FCMGE_H:
7297 fcmp(vf, rd, rn, rm, ge);
7298 break;
7299 case NEON_FACGE_H:
7300 fabscmp(vf, rd, rn, rm, ge);
7301 break;
7302 case NEON_FCMGT_H:
7303 fcmp(vf, rd, rn, rm, gt);
7304 break;
7305 case NEON_FACGT_H:
7306 fabscmp(vf, rd, rn, rm, gt);
7307 break;
7308 default:
7309 VIXL_UNIMPLEMENTED();
7310 break;
7311 }
7312}
7313
Carey Williams2809e6c2018-03-13 12:24:16 +00007314void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7315 NEONFormatDecoder nfd(instr);
7316 SimVRegister& rd = ReadVRegister(instr->GetRd());
7317 SimVRegister& rn = ReadVRegister(instr->GetRn());
7318 SimVRegister& rm = ReadVRegister(instr->GetRm());
7319 int rot = 0;
7320 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01007321 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
7322 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01007323 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01007324 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
7325 rot = instr->GetImmRotFcadd();
7326 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01007327 } else {
7328 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01007329 case NEON_SDOT:
7330 sdot(vf, rd, rn, rm);
7331 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007332 case NEON_SQRDMLAH:
7333 sqrdmlah(vf, rd, rn, rm);
7334 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007335 case NEON_UDOT:
7336 udot(vf, rd, rn, rm);
7337 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007338 case NEON_SQRDMLSH:
7339 sqrdmlsh(vf, rd, rn, rm);
7340 break;
7341 default:
7342 VIXL_UNIMPLEMENTED();
7343 break;
7344 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007345 }
7346}
7347
7348
Alexandre Ramesd3832962016-07-04 15:03:43 +01007349void Simulator::VisitNEON3Different(const Instruction* instr) {
7350 NEONFormatDecoder nfd(instr);
7351 VectorFormat vf = nfd.GetVectorFormat();
7352 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7353
7354 SimVRegister& rd = ReadVRegister(instr->GetRd());
7355 SimVRegister& rn = ReadVRegister(instr->GetRn());
7356 SimVRegister& rm = ReadVRegister(instr->GetRm());
7357
7358 switch (instr->Mask(NEON3DifferentMask)) {
7359 case NEON_PMULL:
7360 pmull(vf_l, rd, rn, rm);
7361 break;
7362 case NEON_PMULL2:
7363 pmull2(vf_l, rd, rn, rm);
7364 break;
7365 case NEON_UADDL:
7366 uaddl(vf_l, rd, rn, rm);
7367 break;
7368 case NEON_UADDL2:
7369 uaddl2(vf_l, rd, rn, rm);
7370 break;
7371 case NEON_SADDL:
7372 saddl(vf_l, rd, rn, rm);
7373 break;
7374 case NEON_SADDL2:
7375 saddl2(vf_l, rd, rn, rm);
7376 break;
7377 case NEON_USUBL:
7378 usubl(vf_l, rd, rn, rm);
7379 break;
7380 case NEON_USUBL2:
7381 usubl2(vf_l, rd, rn, rm);
7382 break;
7383 case NEON_SSUBL:
7384 ssubl(vf_l, rd, rn, rm);
7385 break;
7386 case NEON_SSUBL2:
7387 ssubl2(vf_l, rd, rn, rm);
7388 break;
7389 case NEON_SABAL:
7390 sabal(vf_l, rd, rn, rm);
7391 break;
7392 case NEON_SABAL2:
7393 sabal2(vf_l, rd, rn, rm);
7394 break;
7395 case NEON_UABAL:
7396 uabal(vf_l, rd, rn, rm);
7397 break;
7398 case NEON_UABAL2:
7399 uabal2(vf_l, rd, rn, rm);
7400 break;
7401 case NEON_SABDL:
7402 sabdl(vf_l, rd, rn, rm);
7403 break;
7404 case NEON_SABDL2:
7405 sabdl2(vf_l, rd, rn, rm);
7406 break;
7407 case NEON_UABDL:
7408 uabdl(vf_l, rd, rn, rm);
7409 break;
7410 case NEON_UABDL2:
7411 uabdl2(vf_l, rd, rn, rm);
7412 break;
7413 case NEON_SMLAL:
7414 smlal(vf_l, rd, rn, rm);
7415 break;
7416 case NEON_SMLAL2:
7417 smlal2(vf_l, rd, rn, rm);
7418 break;
7419 case NEON_UMLAL:
7420 umlal(vf_l, rd, rn, rm);
7421 break;
7422 case NEON_UMLAL2:
7423 umlal2(vf_l, rd, rn, rm);
7424 break;
7425 case NEON_SMLSL:
7426 smlsl(vf_l, rd, rn, rm);
7427 break;
7428 case NEON_SMLSL2:
7429 smlsl2(vf_l, rd, rn, rm);
7430 break;
7431 case NEON_UMLSL:
7432 umlsl(vf_l, rd, rn, rm);
7433 break;
7434 case NEON_UMLSL2:
7435 umlsl2(vf_l, rd, rn, rm);
7436 break;
7437 case NEON_SMULL:
7438 smull(vf_l, rd, rn, rm);
7439 break;
7440 case NEON_SMULL2:
7441 smull2(vf_l, rd, rn, rm);
7442 break;
7443 case NEON_UMULL:
7444 umull(vf_l, rd, rn, rm);
7445 break;
7446 case NEON_UMULL2:
7447 umull2(vf_l, rd, rn, rm);
7448 break;
7449 case NEON_SQDMLAL:
7450 sqdmlal(vf_l, rd, rn, rm);
7451 break;
7452 case NEON_SQDMLAL2:
7453 sqdmlal2(vf_l, rd, rn, rm);
7454 break;
7455 case NEON_SQDMLSL:
7456 sqdmlsl(vf_l, rd, rn, rm);
7457 break;
7458 case NEON_SQDMLSL2:
7459 sqdmlsl2(vf_l, rd, rn, rm);
7460 break;
7461 case NEON_SQDMULL:
7462 sqdmull(vf_l, rd, rn, rm);
7463 break;
7464 case NEON_SQDMULL2:
7465 sqdmull2(vf_l, rd, rn, rm);
7466 break;
7467 case NEON_UADDW:
7468 uaddw(vf_l, rd, rn, rm);
7469 break;
7470 case NEON_UADDW2:
7471 uaddw2(vf_l, rd, rn, rm);
7472 break;
7473 case NEON_SADDW:
7474 saddw(vf_l, rd, rn, rm);
7475 break;
7476 case NEON_SADDW2:
7477 saddw2(vf_l, rd, rn, rm);
7478 break;
7479 case NEON_USUBW:
7480 usubw(vf_l, rd, rn, rm);
7481 break;
7482 case NEON_USUBW2:
7483 usubw2(vf_l, rd, rn, rm);
7484 break;
7485 case NEON_SSUBW:
7486 ssubw(vf_l, rd, rn, rm);
7487 break;
7488 case NEON_SSUBW2:
7489 ssubw2(vf_l, rd, rn, rm);
7490 break;
7491 case NEON_ADDHN:
7492 addhn(vf, rd, rn, rm);
7493 break;
7494 case NEON_ADDHN2:
7495 addhn2(vf, rd, rn, rm);
7496 break;
7497 case NEON_RADDHN:
7498 raddhn(vf, rd, rn, rm);
7499 break;
7500 case NEON_RADDHN2:
7501 raddhn2(vf, rd, rn, rm);
7502 break;
7503 case NEON_SUBHN:
7504 subhn(vf, rd, rn, rm);
7505 break;
7506 case NEON_SUBHN2:
7507 subhn2(vf, rd, rn, rm);
7508 break;
7509 case NEON_RSUBHN:
7510 rsubhn(vf, rd, rn, rm);
7511 break;
7512 case NEON_RSUBHN2:
7513 rsubhn2(vf, rd, rn, rm);
7514 break;
7515 default:
7516 VIXL_UNIMPLEMENTED();
7517 }
7518}
7519
7520
7521void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7522 NEONFormatDecoder nfd(instr);
7523
Jacob Bramleyca789742018-09-13 14:25:46 +01007524 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7525
Alexandre Ramesd3832962016-07-04 15:03:43 +01007526 SimVRegister& rd = ReadVRegister(instr->GetRd());
7527 SimVRegister& rn = ReadVRegister(instr->GetRn());
7528
Jacob Bramleyca789742018-09-13 14:25:46 +01007529 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7530 VectorFormat vf = nfd.GetVectorFormat(&map_half);
7531 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7532 case NEON_FMAXV_H:
7533 fmaxv(vf, rd, rn);
7534 break;
7535 case NEON_FMINV_H:
7536 fminv(vf, rd, rn);
7537 break;
7538 case NEON_FMAXNMV_H:
7539 fmaxnmv(vf, rd, rn);
7540 break;
7541 case NEON_FMINNMV_H:
7542 fminnmv(vf, rd, rn);
7543 break;
7544 default:
7545 VIXL_UNIMPLEMENTED();
7546 }
7547 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7548 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01007549 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7550
7551 switch (instr->Mask(NEONAcrossLanesFPMask)) {
7552 case NEON_FMAXV:
7553 fmaxv(vf, rd, rn);
7554 break;
7555 case NEON_FMINV:
7556 fminv(vf, rd, rn);
7557 break;
7558 case NEON_FMAXNMV:
7559 fmaxnmv(vf, rd, rn);
7560 break;
7561 case NEON_FMINNMV:
7562 fminnmv(vf, rd, rn);
7563 break;
7564 default:
7565 VIXL_UNIMPLEMENTED();
7566 }
7567 } else {
7568 VectorFormat vf = nfd.GetVectorFormat();
7569
7570 switch (instr->Mask(NEONAcrossLanesMask)) {
7571 case NEON_ADDV:
7572 addv(vf, rd, rn);
7573 break;
7574 case NEON_SMAXV:
7575 smaxv(vf, rd, rn);
7576 break;
7577 case NEON_SMINV:
7578 sminv(vf, rd, rn);
7579 break;
7580 case NEON_UMAXV:
7581 umaxv(vf, rd, rn);
7582 break;
7583 case NEON_UMINV:
7584 uminv(vf, rd, rn);
7585 break;
7586 case NEON_SADDLV:
7587 saddlv(vf, rd, rn);
7588 break;
7589 case NEON_UADDLV:
7590 uaddlv(vf, rd, rn);
7591 break;
7592 default:
7593 VIXL_UNIMPLEMENTED();
7594 }
7595 }
7596}
7597
7598
7599void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7600 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01007601 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007602 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01007603 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007604 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7605
7606 SimVRegister& rd = ReadVRegister(instr->GetRd());
7607 SimVRegister& rn = ReadVRegister(instr->GetRn());
7608
7609 ByElementOp Op = NULL;
7610
7611 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007612 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007613 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007614 int index_hlm = (index << 1) | instr->GetNEONM();
7615
7616 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
7617 // These are oddballs and are best handled as special cases.
7618 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
7619 // - The index is always H:L:M.
7620 case NEON_FMLAL_H_byelement:
7621 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7622 return;
7623 case NEON_FMLAL2_H_byelement:
7624 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7625 return;
7626 case NEON_FMLSL_H_byelement:
7627 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7628 return;
7629 case NEON_FMLSL2_H_byelement:
7630 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7631 return;
7632 }
7633
Alexandre Ramesd3832962016-07-04 15:03:43 +01007634 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007635 rm_reg = rm_low_reg;
7636 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007637 }
7638
7639 switch (instr->Mask(NEONByIndexedElementMask)) {
7640 case NEON_MUL_byelement:
7641 Op = &Simulator::mul;
7642 vf = vf_r;
7643 break;
7644 case NEON_MLA_byelement:
7645 Op = &Simulator::mla;
7646 vf = vf_r;
7647 break;
7648 case NEON_MLS_byelement:
7649 Op = &Simulator::mls;
7650 vf = vf_r;
7651 break;
7652 case NEON_SQDMULH_byelement:
7653 Op = &Simulator::sqdmulh;
7654 vf = vf_r;
7655 break;
7656 case NEON_SQRDMULH_byelement:
7657 Op = &Simulator::sqrdmulh;
7658 vf = vf_r;
7659 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007660 case NEON_SDOT_byelement:
7661 Op = &Simulator::sdot;
7662 vf = vf_r;
7663 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007664 case NEON_SQRDMLAH_byelement:
7665 Op = &Simulator::sqrdmlah;
7666 vf = vf_r;
7667 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007668 case NEON_UDOT_byelement:
7669 Op = &Simulator::udot;
7670 vf = vf_r;
7671 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007672 case NEON_SQRDMLSH_byelement:
7673 Op = &Simulator::sqrdmlsh;
7674 vf = vf_r;
7675 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007676 case NEON_SMULL_byelement:
7677 if (instr->Mask(NEON_Q)) {
7678 Op = &Simulator::smull2;
7679 } else {
7680 Op = &Simulator::smull;
7681 }
7682 break;
7683 case NEON_UMULL_byelement:
7684 if (instr->Mask(NEON_Q)) {
7685 Op = &Simulator::umull2;
7686 } else {
7687 Op = &Simulator::umull;
7688 }
7689 break;
7690 case NEON_SMLAL_byelement:
7691 if (instr->Mask(NEON_Q)) {
7692 Op = &Simulator::smlal2;
7693 } else {
7694 Op = &Simulator::smlal;
7695 }
7696 break;
7697 case NEON_UMLAL_byelement:
7698 if (instr->Mask(NEON_Q)) {
7699 Op = &Simulator::umlal2;
7700 } else {
7701 Op = &Simulator::umlal;
7702 }
7703 break;
7704 case NEON_SMLSL_byelement:
7705 if (instr->Mask(NEON_Q)) {
7706 Op = &Simulator::smlsl2;
7707 } else {
7708 Op = &Simulator::smlsl;
7709 }
7710 break;
7711 case NEON_UMLSL_byelement:
7712 if (instr->Mask(NEON_Q)) {
7713 Op = &Simulator::umlsl2;
7714 } else {
7715 Op = &Simulator::umlsl;
7716 }
7717 break;
7718 case NEON_SQDMULL_byelement:
7719 if (instr->Mask(NEON_Q)) {
7720 Op = &Simulator::sqdmull2;
7721 } else {
7722 Op = &Simulator::sqdmull;
7723 }
7724 break;
7725 case NEON_SQDMLAL_byelement:
7726 if (instr->Mask(NEON_Q)) {
7727 Op = &Simulator::sqdmlal2;
7728 } else {
7729 Op = &Simulator::sqdmlal;
7730 }
7731 break;
7732 case NEON_SQDMLSL_byelement:
7733 if (instr->Mask(NEON_Q)) {
7734 Op = &Simulator::sqdmlsl2;
7735 } else {
7736 Op = &Simulator::sqdmlsl;
7737 }
7738 break;
7739 default:
7740 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01007741 if (instr->GetFPType() == 0) {
7742 rm_reg &= 0xf;
7743 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7744 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007745 index = (index << 1) | instr->GetNEONL();
7746 }
7747
7748 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7749
7750 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01007751 case NEON_FMUL_H_byelement:
7752 vf = vf_half;
7753 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007754 case NEON_FMUL_byelement:
7755 Op = &Simulator::fmul;
7756 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007757 case NEON_FMLA_H_byelement:
7758 vf = vf_half;
7759 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007760 case NEON_FMLA_byelement:
7761 Op = &Simulator::fmla;
7762 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007763 case NEON_FMLS_H_byelement:
7764 vf = vf_half;
7765 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007766 case NEON_FMLS_byelement:
7767 Op = &Simulator::fmls;
7768 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007769 case NEON_FMULX_H_byelement:
7770 vf = vf_half;
7771 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007772 case NEON_FMULX_byelement:
7773 Op = &Simulator::fmulx;
7774 break;
7775 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007776 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00007777 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007778 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00007779 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007780 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007781 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
7782 case NEON_FCMLA_byelement:
7783 vf = vf_r;
7784 fcmla(vf,
7785 rd,
7786 rn,
7787 ReadVRegister(instr->GetRm()),
7788 index,
7789 instr->GetImmRotFcmlaSca());
7790 return;
7791 default:
7792 VIXL_UNIMPLEMENTED();
7793 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007794 }
7795 }
7796
7797 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
7798}
7799
7800
7801void Simulator::VisitNEONCopy(const Instruction* instr) {
7802 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7803 VectorFormat vf = nfd.GetVectorFormat();
7804
7805 SimVRegister& rd = ReadVRegister(instr->GetRd());
7806 SimVRegister& rn = ReadVRegister(instr->GetRn());
7807 int imm5 = instr->GetImmNEON5();
7808 int tz = CountTrailingZeros(imm5, 32);
7809 int reg_index = imm5 >> (tz + 1);
7810
7811 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7812 int imm4 = instr->GetImmNEON4();
7813 int rn_index = imm4 >> tz;
7814 ins_element(vf, rd, reg_index, rn, rn_index);
7815 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7816 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7817 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7818 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7819 value &= MaxUintFromFormat(vf);
7820 WriteXRegister(instr->GetRd(), value);
7821 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7822 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7823 if (instr->GetNEONQ()) {
7824 WriteXRegister(instr->GetRd(), value);
7825 } else {
7826 WriteWRegister(instr->GetRd(), (int32_t)value);
7827 }
7828 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7829 dup_element(vf, rd, rn, reg_index);
7830 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7831 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7832 } else {
7833 VIXL_UNIMPLEMENTED();
7834 }
7835}
7836
7837
7838void Simulator::VisitNEONExtract(const Instruction* instr) {
7839 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7840 VectorFormat vf = nfd.GetVectorFormat();
7841 SimVRegister& rd = ReadVRegister(instr->GetRd());
7842 SimVRegister& rn = ReadVRegister(instr->GetRn());
7843 SimVRegister& rm = ReadVRegister(instr->GetRm());
7844 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7845 int index = instr->GetImmNEONExt();
7846 ext(vf, rd, rn, rm, index);
7847 } else {
7848 VIXL_UNIMPLEMENTED();
7849 }
7850}
7851
7852
7853void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7854 AddrMode addr_mode) {
7855 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7856 VectorFormat vf = nfd.GetVectorFormat();
7857
7858 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7859 int reg_size = RegisterSizeInBytesFromFormat(vf);
7860
7861 int reg[4];
7862 uint64_t addr[4];
7863 for (int i = 0; i < 4; i++) {
7864 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7865 addr[i] = addr_base + (i * reg_size);
7866 }
Jacob Bramley423e5422019-11-13 19:15:55 +00007867 int struct_parts = 1;
7868 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007869 bool log_read = true;
7870
Martyn Capewell32009e32016-10-27 11:00:37 +01007871 // Bit 23 determines whether this is an offset or post-index addressing mode.
7872 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7873 // register or immediate in post-index mode.
7874 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007875 VIXL_UNREACHABLE();
7876 }
7877
7878 // We use the PostIndex mask here, as it works in this case for both Offset
7879 // and PostIndex addressing.
7880 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7881 case NEON_LD1_4v:
7882 case NEON_LD1_4v_post:
7883 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007884 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007885 VIXL_FALLTHROUGH();
7886 case NEON_LD1_3v:
7887 case NEON_LD1_3v_post:
7888 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007889 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007890 VIXL_FALLTHROUGH();
7891 case NEON_LD1_2v:
7892 case NEON_LD1_2v_post:
7893 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007894 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007895 VIXL_FALLTHROUGH();
7896 case NEON_LD1_1v:
7897 case NEON_LD1_1v_post:
7898 ld1(vf, ReadVRegister(reg[0]), addr[0]);
7899 break;
7900 case NEON_ST1_4v:
7901 case NEON_ST1_4v_post:
7902 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007903 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007904 VIXL_FALLTHROUGH();
7905 case NEON_ST1_3v:
7906 case NEON_ST1_3v_post:
7907 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007908 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007909 VIXL_FALLTHROUGH();
7910 case NEON_ST1_2v:
7911 case NEON_ST1_2v_post:
7912 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007913 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007914 VIXL_FALLTHROUGH();
7915 case NEON_ST1_1v:
7916 case NEON_ST1_1v_post:
7917 st1(vf, ReadVRegister(reg[0]), addr[0]);
7918 log_read = false;
7919 break;
7920 case NEON_LD2_post:
7921 case NEON_LD2:
7922 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007923 struct_parts = 2;
7924 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007925 break;
7926 case NEON_ST2:
7927 case NEON_ST2_post:
7928 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007929 struct_parts = 2;
7930 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01007931 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007932 break;
7933 case NEON_LD3_post:
7934 case NEON_LD3:
7935 ld3(vf,
7936 ReadVRegister(reg[0]),
7937 ReadVRegister(reg[1]),
7938 ReadVRegister(reg[2]),
7939 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007940 struct_parts = 3;
7941 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007942 break;
7943 case NEON_ST3:
7944 case NEON_ST3_post:
7945 st3(vf,
7946 ReadVRegister(reg[0]),
7947 ReadVRegister(reg[1]),
7948 ReadVRegister(reg[2]),
7949 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007950 struct_parts = 3;
7951 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01007952 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007953 break;
7954 case NEON_ST4:
7955 case NEON_ST4_post:
7956 st4(vf,
7957 ReadVRegister(reg[0]),
7958 ReadVRegister(reg[1]),
7959 ReadVRegister(reg[2]),
7960 ReadVRegister(reg[3]),
7961 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007962 struct_parts = 4;
7963 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01007964 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007965 break;
7966 case NEON_LD4_post:
7967 case NEON_LD4:
7968 ld4(vf,
7969 ReadVRegister(reg[0]),
7970 ReadVRegister(reg[1]),
7971 ReadVRegister(reg[2]),
7972 ReadVRegister(reg[3]),
7973 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007974 struct_parts = 4;
7975 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007976 break;
7977 default:
7978 VIXL_UNIMPLEMENTED();
7979 }
7980
Jacob Bramley7eb3e212019-11-22 17:28:05 +00007981 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00007982 if (do_trace) {
7983 PrintRegisterFormat print_format =
7984 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
7985 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007986 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00007987 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01007988 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00007989 op = "->";
7990 // Stores don't represent a change to the source register's value, so only
7991 // print the relevant part of the value.
7992 print_format = GetPrintRegPartial(print_format);
7993 }
7994
7995 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
7996 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
7997 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
7998 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007999 }
8000 }
8001
8002 if (addr_mode == PostIndex) {
8003 int rm = instr->GetRm();
8004 // The immediate post index addressing mode is indicated by rm = 31.
8005 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00008006 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01008007 : ReadXRegister(rm);
8008 WriteXRegister(instr->GetRn(), addr_base);
8009 } else {
8010 VIXL_ASSERT(addr_mode == Offset);
8011 }
8012}
8013
8014
8015void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8016 NEONLoadStoreMultiStructHelper(instr, Offset);
8017}
8018
8019
8020void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8021 const Instruction* instr) {
8022 NEONLoadStoreMultiStructHelper(instr, PostIndex);
8023}
8024
8025
8026void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8027 AddrMode addr_mode) {
8028 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8029 int rt = instr->GetRt();
8030
Martyn Capewell32009e32016-10-27 11:00:37 +01008031 // Bit 23 determines whether this is an offset or post-index addressing mode.
8032 // In offset mode, bits 20 to 16 should be zero; these bits encode the
8033 // register or immediate in post-index mode.
8034 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008035 VIXL_UNREACHABLE();
8036 }
8037
8038 // We use the PostIndex mask here, as it works in this case for both Offset
8039 // and PostIndex addressing.
8040 bool do_load = false;
8041
Jacob Bramley423e5422019-11-13 19:15:55 +00008042 bool replicating = false;
8043
Alexandre Ramesd3832962016-07-04 15:03:43 +01008044 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8045 VectorFormat vf_t = nfd.GetVectorFormat();
8046
8047 VectorFormat vf = kFormat16B;
8048 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8049 case NEON_LD1_b:
8050 case NEON_LD1_b_post:
8051 case NEON_LD2_b:
8052 case NEON_LD2_b_post:
8053 case NEON_LD3_b:
8054 case NEON_LD3_b_post:
8055 case NEON_LD4_b:
8056 case NEON_LD4_b_post:
8057 do_load = true;
8058 VIXL_FALLTHROUGH();
8059 case NEON_ST1_b:
8060 case NEON_ST1_b_post:
8061 case NEON_ST2_b:
8062 case NEON_ST2_b_post:
8063 case NEON_ST3_b:
8064 case NEON_ST3_b_post:
8065 case NEON_ST4_b:
8066 case NEON_ST4_b_post:
8067 break;
8068
8069 case NEON_LD1_h:
8070 case NEON_LD1_h_post:
8071 case NEON_LD2_h:
8072 case NEON_LD2_h_post:
8073 case NEON_LD3_h:
8074 case NEON_LD3_h_post:
8075 case NEON_LD4_h:
8076 case NEON_LD4_h_post:
8077 do_load = true;
8078 VIXL_FALLTHROUGH();
8079 case NEON_ST1_h:
8080 case NEON_ST1_h_post:
8081 case NEON_ST2_h:
8082 case NEON_ST2_h_post:
8083 case NEON_ST3_h:
8084 case NEON_ST3_h_post:
8085 case NEON_ST4_h:
8086 case NEON_ST4_h_post:
8087 vf = kFormat8H;
8088 break;
8089 case NEON_LD1_s:
8090 case NEON_LD1_s_post:
8091 case NEON_LD2_s:
8092 case NEON_LD2_s_post:
8093 case NEON_LD3_s:
8094 case NEON_LD3_s_post:
8095 case NEON_LD4_s:
8096 case NEON_LD4_s_post:
8097 do_load = true;
8098 VIXL_FALLTHROUGH();
8099 case NEON_ST1_s:
8100 case NEON_ST1_s_post:
8101 case NEON_ST2_s:
8102 case NEON_ST2_s_post:
8103 case NEON_ST3_s:
8104 case NEON_ST3_s_post:
8105 case NEON_ST4_s:
8106 case NEON_ST4_s_post: {
8107 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8108 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8109 NEON_LD1_d_post);
8110 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8111 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8112 NEON_ST1_d_post);
8113 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8114 break;
8115 }
8116
8117 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008118 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008119 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008120 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008121 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008122 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008123 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008124 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008125 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008126 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00008127 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008128 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00008129
Alexandre Ramesd3832962016-07-04 15:03:43 +01008130 default:
8131 VIXL_UNIMPLEMENTED();
8132 }
8133
Alexandre Ramesd3832962016-07-04 15:03:43 +01008134 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8135 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00008136 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008137 int rt2 = (rt + 1) % kNumberOfVRegisters;
8138 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8139 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8140 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8141 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00008142 reg_count = 1;
8143 if (replicating) {
8144 VIXL_ASSERT(do_load);
8145 ld1r(vf, ReadVRegister(rt), addr);
8146 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008147 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008148 } else {
8149 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008150 }
8151 break;
8152 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00008153 reg_count = 2;
8154 if (replicating) {
8155 VIXL_ASSERT(do_load);
8156 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8157 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008158 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008159 } else {
8160 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008161 }
8162 break;
8163 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00008164 reg_count = 3;
8165 if (replicating) {
8166 VIXL_ASSERT(do_load);
8167 ld3r(vf,
8168 ReadVRegister(rt),
8169 ReadVRegister(rt2),
8170 ReadVRegister(rt3),
8171 addr);
8172 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008173 ld3(vf,
8174 ReadVRegister(rt),
8175 ReadVRegister(rt2),
8176 ReadVRegister(rt3),
8177 lane,
8178 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008179 } else {
8180 st3(vf,
8181 ReadVRegister(rt),
8182 ReadVRegister(rt2),
8183 ReadVRegister(rt3),
8184 lane,
8185 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008186 }
8187 break;
8188 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00008189 reg_count = 4;
8190 if (replicating) {
8191 VIXL_ASSERT(do_load);
8192 ld4r(vf,
8193 ReadVRegister(rt),
8194 ReadVRegister(rt2),
8195 ReadVRegister(rt3),
8196 ReadVRegister(rt4),
8197 addr);
8198 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008199 ld4(vf,
8200 ReadVRegister(rt),
8201 ReadVRegister(rt2),
8202 ReadVRegister(rt3),
8203 ReadVRegister(rt4),
8204 lane,
8205 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008206 } else {
8207 st4(vf,
8208 ReadVRegister(rt),
8209 ReadVRegister(rt2),
8210 ReadVRegister(rt3),
8211 ReadVRegister(rt4),
8212 lane,
8213 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008214 }
8215 break;
8216 default:
8217 VIXL_UNIMPLEMENTED();
8218 }
8219
Jacob Bramley423e5422019-11-13 19:15:55 +00008220 // Trace registers and/or memory writes.
8221 PrintRegisterFormat print_format =
8222 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8223 if (do_load) {
8224 if (ShouldTraceVRegs()) {
8225 if (replicating) {
8226 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8227 } else {
8228 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8229 }
8230 }
8231 } else {
8232 if (ShouldTraceWrites()) {
8233 // Stores don't represent a change to the source register's value, so only
8234 // print the relevant part of the value.
8235 print_format = GetPrintRegPartial(print_format);
8236 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8237 }
8238 }
8239
Alexandre Ramesd3832962016-07-04 15:03:43 +01008240 if (addr_mode == PostIndex) {
8241 int rm = instr->GetRm();
8242 int lane_size = LaneSizeInBytesFromFormat(vf);
8243 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00008244 addr + ((rm == 31) ? (reg_count * lane_size)
8245 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008246 }
8247}
8248
8249
8250void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8251 NEONLoadStoreSingleStructHelper(instr, Offset);
8252}
8253
8254
8255void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8256 const Instruction* instr) {
8257 NEONLoadStoreSingleStructHelper(instr, PostIndex);
8258}
8259
8260
8261void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8262 SimVRegister& rd = ReadVRegister(instr->GetRd());
8263 int cmode = instr->GetNEONCmode();
8264 int cmode_3_1 = (cmode >> 1) & 7;
8265 int cmode_3 = (cmode >> 3) & 1;
8266 int cmode_2 = (cmode >> 2) & 1;
8267 int cmode_1 = (cmode >> 1) & 1;
8268 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01008269 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008270 int q = instr->GetNEONQ();
8271 int op_bit = instr->GetNEONModImmOp();
8272 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01008273 // Find the format and immediate value
8274 uint64_t imm = 0;
8275 VectorFormat vform = kFormatUndefined;
8276 switch (cmode_3_1) {
8277 case 0x0:
8278 case 0x1:
8279 case 0x2:
8280 case 0x3:
8281 vform = (q == 1) ? kFormat4S : kFormat2S;
8282 imm = imm8 << (8 * cmode_3_1);
8283 break;
8284 case 0x4:
8285 case 0x5:
8286 vform = (q == 1) ? kFormat8H : kFormat4H;
8287 imm = imm8 << (8 * cmode_1);
8288 break;
8289 case 0x6:
8290 vform = (q == 1) ? kFormat4S : kFormat2S;
8291 if (cmode_0 == 0) {
8292 imm = imm8 << 8 | 0x000000ff;
8293 } else {
8294 imm = imm8 << 16 | 0x0000ffff;
8295 }
8296 break;
8297 case 0x7:
8298 if (cmode_0 == 0 && op_bit == 0) {
8299 vform = q ? kFormat16B : kFormat8B;
8300 imm = imm8;
8301 } else if (cmode_0 == 0 && op_bit == 1) {
8302 vform = q ? kFormat2D : kFormat1D;
8303 imm = 0;
8304 for (int i = 0; i < 8; ++i) {
8305 if (imm8 & (1 << i)) {
8306 imm |= (UINT64_C(0xff) << (8 * i));
8307 }
8308 }
8309 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01008310 if (half_enc == 1) {
8311 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01008312 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01008313 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008314 vform = q ? kFormat4S : kFormat2S;
8315 imm = FloatToRawbits(instr->GetImmNEONFP32());
8316 } else if (q == 1) {
8317 vform = kFormat2D;
8318 imm = DoubleToRawbits(instr->GetImmNEONFP64());
8319 } else {
8320 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8321 VisitUnallocated(instr);
8322 }
8323 }
8324 break;
8325 default:
8326 VIXL_UNREACHABLE();
8327 break;
8328 }
8329
8330 // Find the operation
8331 NEONModifiedImmediateOp op;
8332 if (cmode_3 == 0) {
8333 if (cmode_0 == 0) {
8334 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8335 } else { // cmode<0> == '1'
8336 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8337 }
8338 } else { // cmode<3> == '1'
8339 if (cmode_2 == 0) {
8340 if (cmode_0 == 0) {
8341 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8342 } else { // cmode<0> == '1'
8343 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8344 }
8345 } else { // cmode<2> == '1'
8346 if (cmode_1 == 0) {
8347 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8348 } else { // cmode<1> == '1'
8349 if (cmode_0 == 0) {
8350 op = NEONModifiedImmediate_MOVI;
8351 } else { // cmode<0> == '1'
8352 op = NEONModifiedImmediate_MOVI;
8353 }
8354 }
8355 }
8356 }
8357
8358 // Call the logic function
8359 if (op == NEONModifiedImmediate_ORR) {
8360 orr(vform, rd, rd, imm);
8361 } else if (op == NEONModifiedImmediate_BIC) {
8362 bic(vform, rd, rd, imm);
8363 } else if (op == NEONModifiedImmediate_MOVI) {
8364 movi(vform, rd, imm);
8365 } else if (op == NEONModifiedImmediate_MVNI) {
8366 mvni(vform, rd, imm);
8367 } else {
8368 VisitUnimplemented(instr);
8369 }
8370}
8371
8372
8373void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8374 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8375 VectorFormat vf = nfd.GetVectorFormat();
8376
8377 SimVRegister& rd = ReadVRegister(instr->GetRd());
8378 SimVRegister& rn = ReadVRegister(instr->GetRn());
8379
8380 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8381 // These instructions all use a two bit size field, except NOT and RBIT,
8382 // which use the field to encode the operation.
8383 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8384 case NEON_CMEQ_zero_scalar:
8385 cmp(vf, rd, rn, 0, eq);
8386 break;
8387 case NEON_CMGE_zero_scalar:
8388 cmp(vf, rd, rn, 0, ge);
8389 break;
8390 case NEON_CMGT_zero_scalar:
8391 cmp(vf, rd, rn, 0, gt);
8392 break;
8393 case NEON_CMLT_zero_scalar:
8394 cmp(vf, rd, rn, 0, lt);
8395 break;
8396 case NEON_CMLE_zero_scalar:
8397 cmp(vf, rd, rn, 0, le);
8398 break;
8399 case NEON_ABS_scalar:
8400 abs(vf, rd, rn);
8401 break;
8402 case NEON_SQABS_scalar:
8403 abs(vf, rd, rn).SignedSaturate(vf);
8404 break;
8405 case NEON_NEG_scalar:
8406 neg(vf, rd, rn);
8407 break;
8408 case NEON_SQNEG_scalar:
8409 neg(vf, rd, rn).SignedSaturate(vf);
8410 break;
8411 case NEON_SUQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008412 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008413 break;
8414 case NEON_USQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008415 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008416 break;
8417 default:
8418 VIXL_UNIMPLEMENTED();
8419 break;
8420 }
8421 } else {
8422 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8423 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8424
8425 // These instructions all use a one bit size field, except SQXTUN, SQXTN
8426 // and UQXTN, which use a two bit size field.
8427 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8428 case NEON_FRECPE_scalar:
8429 frecpe(fpf, rd, rn, fpcr_rounding);
8430 break;
8431 case NEON_FRECPX_scalar:
8432 frecpx(fpf, rd, rn);
8433 break;
8434 case NEON_FRSQRTE_scalar:
8435 frsqrte(fpf, rd, rn);
8436 break;
8437 case NEON_FCMGT_zero_scalar:
8438 fcmp_zero(fpf, rd, rn, gt);
8439 break;
8440 case NEON_FCMGE_zero_scalar:
8441 fcmp_zero(fpf, rd, rn, ge);
8442 break;
8443 case NEON_FCMEQ_zero_scalar:
8444 fcmp_zero(fpf, rd, rn, eq);
8445 break;
8446 case NEON_FCMLE_zero_scalar:
8447 fcmp_zero(fpf, rd, rn, le);
8448 break;
8449 case NEON_FCMLT_zero_scalar:
8450 fcmp_zero(fpf, rd, rn, lt);
8451 break;
8452 case NEON_SCVTF_scalar:
8453 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8454 break;
8455 case NEON_UCVTF_scalar:
8456 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8457 break;
8458 case NEON_FCVTNS_scalar:
8459 fcvts(fpf, rd, rn, FPTieEven);
8460 break;
8461 case NEON_FCVTNU_scalar:
8462 fcvtu(fpf, rd, rn, FPTieEven);
8463 break;
8464 case NEON_FCVTPS_scalar:
8465 fcvts(fpf, rd, rn, FPPositiveInfinity);
8466 break;
8467 case NEON_FCVTPU_scalar:
8468 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8469 break;
8470 case NEON_FCVTMS_scalar:
8471 fcvts(fpf, rd, rn, FPNegativeInfinity);
8472 break;
8473 case NEON_FCVTMU_scalar:
8474 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8475 break;
8476 case NEON_FCVTZS_scalar:
8477 fcvts(fpf, rd, rn, FPZero);
8478 break;
8479 case NEON_FCVTZU_scalar:
8480 fcvtu(fpf, rd, rn, FPZero);
8481 break;
8482 case NEON_FCVTAS_scalar:
8483 fcvts(fpf, rd, rn, FPTieAway);
8484 break;
8485 case NEON_FCVTAU_scalar:
8486 fcvtu(fpf, rd, rn, FPTieAway);
8487 break;
8488 case NEON_FCVTXN_scalar:
8489 // Unlike all of the other FP instructions above, fcvtxn encodes dest
8490 // size S as size<0>=1. There's only one case, so we ignore the form.
8491 VIXL_ASSERT(instr->ExtractBit(22) == 1);
8492 fcvtxn(kFormatS, rd, rn);
8493 break;
8494 default:
8495 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8496 case NEON_SQXTN_scalar:
8497 sqxtn(vf, rd, rn);
8498 break;
8499 case NEON_UQXTN_scalar:
8500 uqxtn(vf, rd, rn);
8501 break;
8502 case NEON_SQXTUN_scalar:
8503 sqxtun(vf, rd, rn);
8504 break;
8505 default:
8506 VIXL_UNIMPLEMENTED();
8507 }
8508 }
8509 }
8510}
8511
8512
Jacob Bramleyca789742018-09-13 14:25:46 +01008513void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8514 VectorFormat fpf = kFormatH;
8515 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8516
8517 SimVRegister& rd = ReadVRegister(instr->GetRd());
8518 SimVRegister& rn = ReadVRegister(instr->GetRn());
8519
8520 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8521 case NEON_FRECPE_H_scalar:
8522 frecpe(fpf, rd, rn, fpcr_rounding);
8523 break;
8524 case NEON_FRECPX_H_scalar:
8525 frecpx(fpf, rd, rn);
8526 break;
8527 case NEON_FRSQRTE_H_scalar:
8528 frsqrte(fpf, rd, rn);
8529 break;
8530 case NEON_FCMGT_H_zero_scalar:
8531 fcmp_zero(fpf, rd, rn, gt);
8532 break;
8533 case NEON_FCMGE_H_zero_scalar:
8534 fcmp_zero(fpf, rd, rn, ge);
8535 break;
8536 case NEON_FCMEQ_H_zero_scalar:
8537 fcmp_zero(fpf, rd, rn, eq);
8538 break;
8539 case NEON_FCMLE_H_zero_scalar:
8540 fcmp_zero(fpf, rd, rn, le);
8541 break;
8542 case NEON_FCMLT_H_zero_scalar:
8543 fcmp_zero(fpf, rd, rn, lt);
8544 break;
8545 case NEON_SCVTF_H_scalar:
8546 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8547 break;
8548 case NEON_UCVTF_H_scalar:
8549 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8550 break;
8551 case NEON_FCVTNS_H_scalar:
8552 fcvts(fpf, rd, rn, FPTieEven);
8553 break;
8554 case NEON_FCVTNU_H_scalar:
8555 fcvtu(fpf, rd, rn, FPTieEven);
8556 break;
8557 case NEON_FCVTPS_H_scalar:
8558 fcvts(fpf, rd, rn, FPPositiveInfinity);
8559 break;
8560 case NEON_FCVTPU_H_scalar:
8561 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8562 break;
8563 case NEON_FCVTMS_H_scalar:
8564 fcvts(fpf, rd, rn, FPNegativeInfinity);
8565 break;
8566 case NEON_FCVTMU_H_scalar:
8567 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8568 break;
8569 case NEON_FCVTZS_H_scalar:
8570 fcvts(fpf, rd, rn, FPZero);
8571 break;
8572 case NEON_FCVTZU_H_scalar:
8573 fcvtu(fpf, rd, rn, FPZero);
8574 break;
8575 case NEON_FCVTAS_H_scalar:
8576 fcvts(fpf, rd, rn, FPTieAway);
8577 break;
8578 case NEON_FCVTAU_H_scalar:
8579 fcvtu(fpf, rd, rn, FPTieAway);
8580 break;
8581 }
8582}
8583
8584
Alexandre Ramesd3832962016-07-04 15:03:43 +01008585void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8586 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8587 VectorFormat vf = nfd.GetVectorFormat();
8588
8589 SimVRegister& rd = ReadVRegister(instr->GetRd());
8590 SimVRegister& rn = ReadVRegister(instr->GetRn());
8591 SimVRegister& rm = ReadVRegister(instr->GetRm());
8592 switch (instr->Mask(NEONScalar3DiffMask)) {
8593 case NEON_SQDMLAL_scalar:
8594 sqdmlal(vf, rd, rn, rm);
8595 break;
8596 case NEON_SQDMLSL_scalar:
8597 sqdmlsl(vf, rd, rn, rm);
8598 break;
8599 case NEON_SQDMULL_scalar:
8600 sqdmull(vf, rd, rn, rm);
8601 break;
8602 default:
8603 VIXL_UNIMPLEMENTED();
8604 }
8605}
8606
8607
8608void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8609 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8610 VectorFormat vf = nfd.GetVectorFormat();
8611
8612 SimVRegister& rd = ReadVRegister(instr->GetRd());
8613 SimVRegister& rn = ReadVRegister(instr->GetRn());
8614 SimVRegister& rm = ReadVRegister(instr->GetRm());
8615
8616 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8617 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8618 switch (instr->Mask(NEONScalar3SameFPMask)) {
8619 case NEON_FMULX_scalar:
8620 fmulx(vf, rd, rn, rm);
8621 break;
8622 case NEON_FACGE_scalar:
8623 fabscmp(vf, rd, rn, rm, ge);
8624 break;
8625 case NEON_FACGT_scalar:
8626 fabscmp(vf, rd, rn, rm, gt);
8627 break;
8628 case NEON_FCMEQ_scalar:
8629 fcmp(vf, rd, rn, rm, eq);
8630 break;
8631 case NEON_FCMGE_scalar:
8632 fcmp(vf, rd, rn, rm, ge);
8633 break;
8634 case NEON_FCMGT_scalar:
8635 fcmp(vf, rd, rn, rm, gt);
8636 break;
8637 case NEON_FRECPS_scalar:
8638 frecps(vf, rd, rn, rm);
8639 break;
8640 case NEON_FRSQRTS_scalar:
8641 frsqrts(vf, rd, rn, rm);
8642 break;
8643 case NEON_FABD_scalar:
8644 fabd(vf, rd, rn, rm);
8645 break;
8646 default:
8647 VIXL_UNIMPLEMENTED();
8648 }
8649 } else {
8650 switch (instr->Mask(NEONScalar3SameMask)) {
8651 case NEON_ADD_scalar:
8652 add(vf, rd, rn, rm);
8653 break;
8654 case NEON_SUB_scalar:
8655 sub(vf, rd, rn, rm);
8656 break;
8657 case NEON_CMEQ_scalar:
8658 cmp(vf, rd, rn, rm, eq);
8659 break;
8660 case NEON_CMGE_scalar:
8661 cmp(vf, rd, rn, rm, ge);
8662 break;
8663 case NEON_CMGT_scalar:
8664 cmp(vf, rd, rn, rm, gt);
8665 break;
8666 case NEON_CMHI_scalar:
8667 cmp(vf, rd, rn, rm, hi);
8668 break;
8669 case NEON_CMHS_scalar:
8670 cmp(vf, rd, rn, rm, hs);
8671 break;
8672 case NEON_CMTST_scalar:
8673 cmptst(vf, rd, rn, rm);
8674 break;
8675 case NEON_USHL_scalar:
8676 ushl(vf, rd, rn, rm);
8677 break;
8678 case NEON_SSHL_scalar:
8679 sshl(vf, rd, rn, rm);
8680 break;
8681 case NEON_SQDMULH_scalar:
8682 sqdmulh(vf, rd, rn, rm);
8683 break;
8684 case NEON_SQRDMULH_scalar:
8685 sqrdmulh(vf, rd, rn, rm);
8686 break;
8687 case NEON_UQADD_scalar:
8688 add(vf, rd, rn, rm).UnsignedSaturate(vf);
8689 break;
8690 case NEON_SQADD_scalar:
8691 add(vf, rd, rn, rm).SignedSaturate(vf);
8692 break;
8693 case NEON_UQSUB_scalar:
8694 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8695 break;
8696 case NEON_SQSUB_scalar:
8697 sub(vf, rd, rn, rm).SignedSaturate(vf);
8698 break;
8699 case NEON_UQSHL_scalar:
8700 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8701 break;
8702 case NEON_SQSHL_scalar:
8703 sshl(vf, rd, rn, rm).SignedSaturate(vf);
8704 break;
8705 case NEON_URSHL_scalar:
8706 ushl(vf, rd, rn, rm).Round(vf);
8707 break;
8708 case NEON_SRSHL_scalar:
8709 sshl(vf, rd, rn, rm).Round(vf);
8710 break;
8711 case NEON_UQRSHL_scalar:
8712 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8713 break;
8714 case NEON_SQRSHL_scalar:
8715 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8716 break;
8717 default:
8718 VIXL_UNIMPLEMENTED();
8719 }
8720 }
8721}
8722
Jacob Bramleyca789742018-09-13 14:25:46 +01008723void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8724 SimVRegister& rd = ReadVRegister(instr->GetRd());
8725 SimVRegister& rn = ReadVRegister(instr->GetRn());
8726 SimVRegister& rm = ReadVRegister(instr->GetRm());
8727
8728 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8729 case NEON_FABD_H_scalar:
8730 fabd(kFormatH, rd, rn, rm);
8731 break;
8732 case NEON_FMULX_H_scalar:
8733 fmulx(kFormatH, rd, rn, rm);
8734 break;
8735 case NEON_FCMEQ_H_scalar:
8736 fcmp(kFormatH, rd, rn, rm, eq);
8737 break;
8738 case NEON_FCMGE_H_scalar:
8739 fcmp(kFormatH, rd, rn, rm, ge);
8740 break;
8741 case NEON_FCMGT_H_scalar:
8742 fcmp(kFormatH, rd, rn, rm, gt);
8743 break;
8744 case NEON_FACGE_H_scalar:
8745 fabscmp(kFormatH, rd, rn, rm, ge);
8746 break;
8747 case NEON_FACGT_H_scalar:
8748 fabscmp(kFormatH, rd, rn, rm, gt);
8749 break;
8750 case NEON_FRECPS_H_scalar:
8751 frecps(kFormatH, rd, rn, rm);
8752 break;
8753 case NEON_FRSQRTS_H_scalar:
8754 frsqrts(kFormatH, rd, rn, rm);
8755 break;
8756 default:
8757 VIXL_UNREACHABLE();
8758 }
8759}
8760
Alexandre Ramesd3832962016-07-04 15:03:43 +01008761
Alexander Gilday43785642018-04-04 13:42:33 +01008762void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8763 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8764 VectorFormat vf = nfd.GetVectorFormat();
8765
8766 SimVRegister& rd = ReadVRegister(instr->GetRd());
8767 SimVRegister& rn = ReadVRegister(instr->GetRn());
8768 SimVRegister& rm = ReadVRegister(instr->GetRm());
8769
8770 switch (instr->Mask(NEONScalar3SameExtraMask)) {
8771 case NEON_SQRDMLAH_scalar:
8772 sqrdmlah(vf, rd, rn, rm);
8773 break;
8774 case NEON_SQRDMLSH_scalar:
8775 sqrdmlsh(vf, rd, rn, rm);
8776 break;
8777 default:
8778 VIXL_UNIMPLEMENTED();
8779 }
8780}
8781
Alexandre Ramesd3832962016-07-04 15:03:43 +01008782void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8783 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8784 VectorFormat vf = nfd.GetVectorFormat();
8785 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8786
8787 SimVRegister& rd = ReadVRegister(instr->GetRd());
8788 SimVRegister& rn = ReadVRegister(instr->GetRn());
8789 ByElementOp Op = NULL;
8790
8791 int rm_reg = instr->GetRm();
8792 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8793 if (instr->GetNEONSize() == 1) {
8794 rm_reg &= 0xf;
8795 index = (index << 1) | instr->GetNEONM();
8796 }
8797
8798 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8799 case NEON_SQDMULL_byelement_scalar:
8800 Op = &Simulator::sqdmull;
8801 break;
8802 case NEON_SQDMLAL_byelement_scalar:
8803 Op = &Simulator::sqdmlal;
8804 break;
8805 case NEON_SQDMLSL_byelement_scalar:
8806 Op = &Simulator::sqdmlsl;
8807 break;
8808 case NEON_SQDMULH_byelement_scalar:
8809 Op = &Simulator::sqdmulh;
8810 vf = vf_r;
8811 break;
8812 case NEON_SQRDMULH_byelement_scalar:
8813 Op = &Simulator::sqrdmulh;
8814 vf = vf_r;
8815 break;
Alexander Gilday43785642018-04-04 13:42:33 +01008816 case NEON_SQRDMLAH_byelement_scalar:
8817 Op = &Simulator::sqrdmlah;
8818 vf = vf_r;
8819 break;
8820 case NEON_SQRDMLSH_byelement_scalar:
8821 Op = &Simulator::sqrdmlsh;
8822 vf = vf_r;
8823 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008824 default:
8825 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8826 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01008827 if (instr->GetFPType() == 0) {
8828 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8829 rm_reg &= 0xf;
8830 vf = kFormatH;
8831 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008832 index = (index << 1) | instr->GetNEONL();
8833 }
8834 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008835 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008836 case NEON_FMUL_byelement_scalar:
8837 Op = &Simulator::fmul;
8838 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008839 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008840 case NEON_FMLA_byelement_scalar:
8841 Op = &Simulator::fmla;
8842 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008843 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008844 case NEON_FMLS_byelement_scalar:
8845 Op = &Simulator::fmls;
8846 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008847 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008848 case NEON_FMULX_byelement_scalar:
8849 Op = &Simulator::fmulx;
8850 break;
8851 default:
8852 VIXL_UNIMPLEMENTED();
8853 }
8854 }
8855
8856 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8857}
8858
8859
8860void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8861 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8862 VectorFormat vf = nfd.GetVectorFormat();
8863
8864 SimVRegister& rd = ReadVRegister(instr->GetRd());
8865 SimVRegister& rn = ReadVRegister(instr->GetRn());
8866
8867 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8868 int imm5 = instr->GetImmNEON5();
8869 int tz = CountTrailingZeros(imm5, 32);
8870 int rn_index = imm5 >> (tz + 1);
8871 dup_element(vf, rd, rn, rn_index);
8872 } else {
8873 VIXL_UNIMPLEMENTED();
8874 }
8875}
8876
8877
8878void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008879 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008880 VectorFormat vf = nfd.GetVectorFormat();
8881
8882 SimVRegister& rd = ReadVRegister(instr->GetRd());
8883 SimVRegister& rn = ReadVRegister(instr->GetRn());
8884 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008885 case NEON_ADDP_scalar: {
8886 // All pairwise operations except ADDP use bit U to differentiate FP16
8887 // from FP32/FP64 variations.
8888 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8889 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008890 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008891 }
8892 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008893 case NEON_FADDP_scalar:
8894 faddp(vf, rd, rn);
8895 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008896 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008897 case NEON_FMAXP_scalar:
8898 fmaxp(vf, rd, rn);
8899 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008900 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008901 case NEON_FMAXNMP_scalar:
8902 fmaxnmp(vf, rd, rn);
8903 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008904 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008905 case NEON_FMINP_scalar:
8906 fminp(vf, rd, rn);
8907 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008908 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008909 case NEON_FMINNMP_scalar:
8910 fminnmp(vf, rd, rn);
8911 break;
8912 default:
8913 VIXL_UNIMPLEMENTED();
8914 }
8915}
8916
8917
8918void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
8919 SimVRegister& rd = ReadVRegister(instr->GetRd());
8920 SimVRegister& rn = ReadVRegister(instr->GetRn());
8921 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8922
8923 static const NEONFormatMap map = {{22, 21, 20, 19},
8924 {NF_UNDEF,
8925 NF_B,
8926 NF_H,
8927 NF_H,
8928 NF_S,
8929 NF_S,
8930 NF_S,
8931 NF_S,
8932 NF_D,
8933 NF_D,
8934 NF_D,
8935 NF_D,
8936 NF_D,
8937 NF_D,
8938 NF_D,
8939 NF_D}};
8940 NEONFormatDecoder nfd(instr, &map);
8941 VectorFormat vf = nfd.GetVectorFormat();
8942
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00008943 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
8944 int immh_immb = instr->GetImmNEONImmhImmb();
8945 int right_shift = (16 << highest_set_bit) - immh_immb;
8946 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008947 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
8948 case NEON_SHL_scalar:
8949 shl(vf, rd, rn, left_shift);
8950 break;
8951 case NEON_SLI_scalar:
8952 sli(vf, rd, rn, left_shift);
8953 break;
8954 case NEON_SQSHL_imm_scalar:
8955 sqshl(vf, rd, rn, left_shift);
8956 break;
8957 case NEON_UQSHL_imm_scalar:
8958 uqshl(vf, rd, rn, left_shift);
8959 break;
8960 case NEON_SQSHLU_scalar:
8961 sqshlu(vf, rd, rn, left_shift);
8962 break;
8963 case NEON_SRI_scalar:
8964 sri(vf, rd, rn, right_shift);
8965 break;
8966 case NEON_SSHR_scalar:
8967 sshr(vf, rd, rn, right_shift);
8968 break;
8969 case NEON_USHR_scalar:
8970 ushr(vf, rd, rn, right_shift);
8971 break;
8972 case NEON_SRSHR_scalar:
8973 sshr(vf, rd, rn, right_shift).Round(vf);
8974 break;
8975 case NEON_URSHR_scalar:
8976 ushr(vf, rd, rn, right_shift).Round(vf);
8977 break;
8978 case NEON_SSRA_scalar:
8979 ssra(vf, rd, rn, right_shift);
8980 break;
8981 case NEON_USRA_scalar:
8982 usra(vf, rd, rn, right_shift);
8983 break;
8984 case NEON_SRSRA_scalar:
8985 srsra(vf, rd, rn, right_shift);
8986 break;
8987 case NEON_URSRA_scalar:
8988 ursra(vf, rd, rn, right_shift);
8989 break;
8990 case NEON_UQSHRN_scalar:
8991 uqshrn(vf, rd, rn, right_shift);
8992 break;
8993 case NEON_UQRSHRN_scalar:
8994 uqrshrn(vf, rd, rn, right_shift);
8995 break;
8996 case NEON_SQSHRN_scalar:
8997 sqshrn(vf, rd, rn, right_shift);
8998 break;
8999 case NEON_SQRSHRN_scalar:
9000 sqrshrn(vf, rd, rn, right_shift);
9001 break;
9002 case NEON_SQSHRUN_scalar:
9003 sqshrun(vf, rd, rn, right_shift);
9004 break;
9005 case NEON_SQRSHRUN_scalar:
9006 sqrshrun(vf, rd, rn, right_shift);
9007 break;
9008 case NEON_FCVTZS_imm_scalar:
9009 fcvts(vf, rd, rn, FPZero, right_shift);
9010 break;
9011 case NEON_FCVTZU_imm_scalar:
9012 fcvtu(vf, rd, rn, FPZero, right_shift);
9013 break;
9014 case NEON_SCVTF_imm_scalar:
9015 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9016 break;
9017 case NEON_UCVTF_imm_scalar:
9018 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9019 break;
9020 default:
9021 VIXL_UNIMPLEMENTED();
9022 }
9023}
9024
9025
9026void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9027 SimVRegister& rd = ReadVRegister(instr->GetRd());
9028 SimVRegister& rn = ReadVRegister(instr->GetRn());
9029 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9030
9031 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9032 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9033 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01009034 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
9035 NF_4H, NF_8H, NF_4H, NF_8H,
9036 NF_2S, NF_4S, NF_2S, NF_4S,
9037 NF_2S, NF_4S, NF_2S, NF_4S,
9038 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9039 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9040 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9041 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01009042 NEONFormatDecoder nfd(instr, &map);
9043 VectorFormat vf = nfd.GetVectorFormat();
9044
9045 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9046 static const NEONFormatMap map_l =
9047 {{22, 21, 20, 19},
9048 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9049 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9050
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00009051 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9052 int immh_immb = instr->GetImmNEONImmhImmb();
9053 int right_shift = (16 << highest_set_bit) - immh_immb;
9054 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009055
9056 switch (instr->Mask(NEONShiftImmediateMask)) {
9057 case NEON_SHL:
9058 shl(vf, rd, rn, left_shift);
9059 break;
9060 case NEON_SLI:
9061 sli(vf, rd, rn, left_shift);
9062 break;
9063 case NEON_SQSHLU:
9064 sqshlu(vf, rd, rn, left_shift);
9065 break;
9066 case NEON_SRI:
9067 sri(vf, rd, rn, right_shift);
9068 break;
9069 case NEON_SSHR:
9070 sshr(vf, rd, rn, right_shift);
9071 break;
9072 case NEON_USHR:
9073 ushr(vf, rd, rn, right_shift);
9074 break;
9075 case NEON_SRSHR:
9076 sshr(vf, rd, rn, right_shift).Round(vf);
9077 break;
9078 case NEON_URSHR:
9079 ushr(vf, rd, rn, right_shift).Round(vf);
9080 break;
9081 case NEON_SSRA:
9082 ssra(vf, rd, rn, right_shift);
9083 break;
9084 case NEON_USRA:
9085 usra(vf, rd, rn, right_shift);
9086 break;
9087 case NEON_SRSRA:
9088 srsra(vf, rd, rn, right_shift);
9089 break;
9090 case NEON_URSRA:
9091 ursra(vf, rd, rn, right_shift);
9092 break;
9093 case NEON_SQSHL_imm:
9094 sqshl(vf, rd, rn, left_shift);
9095 break;
9096 case NEON_UQSHL_imm:
9097 uqshl(vf, rd, rn, left_shift);
9098 break;
9099 case NEON_SCVTF_imm:
9100 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9101 break;
9102 case NEON_UCVTF_imm:
9103 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9104 break;
9105 case NEON_FCVTZS_imm:
9106 fcvts(vf, rd, rn, FPZero, right_shift);
9107 break;
9108 case NEON_FCVTZU_imm:
9109 fcvtu(vf, rd, rn, FPZero, right_shift);
9110 break;
9111 case NEON_SSHLL:
9112 vf = vf_l;
9113 if (instr->Mask(NEON_Q)) {
9114 sshll2(vf, rd, rn, left_shift);
9115 } else {
9116 sshll(vf, rd, rn, left_shift);
9117 }
9118 break;
9119 case NEON_USHLL:
9120 vf = vf_l;
9121 if (instr->Mask(NEON_Q)) {
9122 ushll2(vf, rd, rn, left_shift);
9123 } else {
9124 ushll(vf, rd, rn, left_shift);
9125 }
9126 break;
9127 case NEON_SHRN:
9128 if (instr->Mask(NEON_Q)) {
9129 shrn2(vf, rd, rn, right_shift);
9130 } else {
9131 shrn(vf, rd, rn, right_shift);
9132 }
9133 break;
9134 case NEON_RSHRN:
9135 if (instr->Mask(NEON_Q)) {
9136 rshrn2(vf, rd, rn, right_shift);
9137 } else {
9138 rshrn(vf, rd, rn, right_shift);
9139 }
9140 break;
9141 case NEON_UQSHRN:
9142 if (instr->Mask(NEON_Q)) {
9143 uqshrn2(vf, rd, rn, right_shift);
9144 } else {
9145 uqshrn(vf, rd, rn, right_shift);
9146 }
9147 break;
9148 case NEON_UQRSHRN:
9149 if (instr->Mask(NEON_Q)) {
9150 uqrshrn2(vf, rd, rn, right_shift);
9151 } else {
9152 uqrshrn(vf, rd, rn, right_shift);
9153 }
9154 break;
9155 case NEON_SQSHRN:
9156 if (instr->Mask(NEON_Q)) {
9157 sqshrn2(vf, rd, rn, right_shift);
9158 } else {
9159 sqshrn(vf, rd, rn, right_shift);
9160 }
9161 break;
9162 case NEON_SQRSHRN:
9163 if (instr->Mask(NEON_Q)) {
9164 sqrshrn2(vf, rd, rn, right_shift);
9165 } else {
9166 sqrshrn(vf, rd, rn, right_shift);
9167 }
9168 break;
9169 case NEON_SQSHRUN:
9170 if (instr->Mask(NEON_Q)) {
9171 sqshrun2(vf, rd, rn, right_shift);
9172 } else {
9173 sqshrun(vf, rd, rn, right_shift);
9174 }
9175 break;
9176 case NEON_SQRSHRUN:
9177 if (instr->Mask(NEON_Q)) {
9178 sqrshrun2(vf, rd, rn, right_shift);
9179 } else {
9180 sqrshrun(vf, rd, rn, right_shift);
9181 }
9182 break;
9183 default:
9184 VIXL_UNIMPLEMENTED();
9185 }
9186}
9187
9188
9189void Simulator::VisitNEONTable(const Instruction* instr) {
9190 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9191 VectorFormat vf = nfd.GetVectorFormat();
9192
9193 SimVRegister& rd = ReadVRegister(instr->GetRd());
9194 SimVRegister& rn = ReadVRegister(instr->GetRn());
9195 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9196 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9197 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9198 SimVRegister& rm = ReadVRegister(instr->GetRm());
9199
9200 switch (instr->Mask(NEONTableMask)) {
9201 case NEON_TBL_1v:
9202 tbl(vf, rd, rn, rm);
9203 break;
9204 case NEON_TBL_2v:
9205 tbl(vf, rd, rn, rn2, rm);
9206 break;
9207 case NEON_TBL_3v:
9208 tbl(vf, rd, rn, rn2, rn3, rm);
9209 break;
9210 case NEON_TBL_4v:
9211 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9212 break;
9213 case NEON_TBX_1v:
9214 tbx(vf, rd, rn, rm);
9215 break;
9216 case NEON_TBX_2v:
9217 tbx(vf, rd, rn, rn2, rm);
9218 break;
9219 case NEON_TBX_3v:
9220 tbx(vf, rd, rn, rn2, rn3, rm);
9221 break;
9222 case NEON_TBX_4v:
9223 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9224 break;
9225 default:
9226 VIXL_UNIMPLEMENTED();
9227 }
9228}
9229
9230
9231void Simulator::VisitNEONPerm(const Instruction* instr) {
9232 NEONFormatDecoder nfd(instr);
9233 VectorFormat vf = nfd.GetVectorFormat();
9234
9235 SimVRegister& rd = ReadVRegister(instr->GetRd());
9236 SimVRegister& rn = ReadVRegister(instr->GetRn());
9237 SimVRegister& rm = ReadVRegister(instr->GetRm());
9238
9239 switch (instr->Mask(NEONPermMask)) {
9240 case NEON_TRN1:
9241 trn1(vf, rd, rn, rm);
9242 break;
9243 case NEON_TRN2:
9244 trn2(vf, rd, rn, rm);
9245 break;
9246 case NEON_UZP1:
9247 uzp1(vf, rd, rn, rm);
9248 break;
9249 case NEON_UZP2:
9250 uzp2(vf, rd, rn, rm);
9251 break;
9252 case NEON_ZIP1:
9253 zip1(vf, rd, rn, rm);
9254 break;
9255 case NEON_ZIP2:
9256 zip2(vf, rd, rn, rm);
9257 break;
9258 default:
9259 VIXL_UNIMPLEMENTED();
9260 }
9261}
9262
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009263void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00009264 SimVRegister& zd = ReadVRegister(instr->GetRd());
9265 SimVRegister& zn = ReadVRegister(instr->GetRn());
9266 SimVRegister& zm = ReadVRegister(instr->GetRm());
9267 SimVRegister temp;
9268
9269 VectorFormat vform = kFormatVnD;
9270 mov(vform, temp, zm);
9271
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009272 switch (instr->Mask(SVEAddressGenerationMask)) {
9273 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009274 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009275 break;
9276 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009277 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009278 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00009279 case ADR_z_az_s_same_scaled:
9280 vform = kFormatVnS;
9281 break;
9282 case ADR_z_az_d_same_scaled:
9283 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009284 break;
9285 default:
9286 VIXL_UNIMPLEMENTED();
9287 break;
9288 }
Martyn Capewell48522f52020-03-16 15:31:19 +00009289
9290 int shift_amount = instr->ExtractBits(11, 10);
9291 shl(vform, temp, temp, shift_amount);
9292 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009293}
9294
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009295void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9296 const Instruction* instr) {
9297 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07009298 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009299 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009300 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07009301 case ORR_z_zi: {
9302 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9303 uint64_t imm = instr->GetSVEImmLogical();
9304 // Valid immediate is a non-zero bits
9305 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009306 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9307 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07009308 SVEFormatFromLaneSizeInBytesLog2(lane_size),
9309 ReadVRegister(instr->GetRd()),
9310 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009311 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07009312 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009313 default:
9314 VIXL_UNIMPLEMENTED();
9315 break;
9316 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009317}
9318
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009319void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9320 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9321 case DUPM_z_i: {
9322 /* DUPM uses the same lane size and immediate encoding as bitwise logical
9323 * immediate instructions. */
9324 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9325 uint64_t imm = instr->GetSVEImmLogical();
9326 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9327 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9328 break;
9329 }
9330 default:
9331 VIXL_UNIMPLEMENTED();
9332 break;
9333 }
9334}
9335
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009336void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07009337 SimVRegister& zd = ReadVRegister(instr->GetRd());
9338 SimVRegister& zn = ReadVRegister(instr->GetRn());
9339 SimVRegister& zm = ReadVRegister(instr->GetRm());
9340 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9341
TatWai Chong13634762019-07-16 16:20:45 -07009342 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07009343 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009344 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009345 logical_op = AND;
9346 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009347 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009348 logical_op = BIC;
9349 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009350 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009351 logical_op = EOR;
9352 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07009353 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009354 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009355 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009356 default:
TatWai Chong13634762019-07-16 16:20:45 -07009357 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009358 VIXL_UNIMPLEMENTED();
9359 break;
9360 }
TatWai Chong13634762019-07-16 16:20:45 -07009361 // Lane size of registers is irrelevant to the bitwise operations, so perform
9362 // the operation on D-sized lanes.
9363 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009364}
9365
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009366void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00009367 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9368 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9369
9370 SimVRegister scratch;
9371 SimVRegister result;
9372
9373 bool for_division = false;
9374 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009375 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009376 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009377 shift_op = ASR;
9378 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009379 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009380 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009381 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009382 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009383 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009384 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009385 break;
9386 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009387 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009388 break;
9389 default:
9390 VIXL_UNIMPLEMENTED();
9391 break;
9392 }
Martyn Capewell83e86612020-02-19 15:46:15 +00009393
9394 std::pair<int, int> shift_and_lane_size =
9395 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9396 unsigned lane_size = shift_and_lane_size.second;
9397 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9398 int shift_dist = shift_and_lane_size.first;
9399
9400 if ((shift_op == ASR) && for_division) {
9401 asrd(vform, result, zdn, shift_dist);
9402 } else {
9403 if (shift_op == LSL) {
9404 // Shift distance is computed differently for LSL. Convert the result.
9405 shift_dist = (8 << lane_size) - shift_dist;
9406 }
9407 dup_immediate(vform, scratch, shift_dist);
9408 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9409 }
9410 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009411}
9412
9413void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9414 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009415 VectorFormat vform = instr->GetSVEVectorFormat();
9416 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9417 SimVRegister& zm = ReadVRegister(instr->GetRn());
9418 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell76c094a2020-02-13 17:26:49 +00009419 SimVRegister result;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009420
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009421 // SVE uses the whole (saturated) lane for the shift amount.
9422 bool shift_in_ls_byte = false;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009423
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009424 switch (form_hash_) {
9425 case Hash("asrr_z_p_zz"):
9426 sshr(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009427 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009428 case Hash("asr_z_p_zz"):
9429 sshr(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009430 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009431 case Hash("lslr_z_p_zz"):
9432 sshl(vform, result, zm, zdn, shift_in_ls_byte);
9433 break;
9434 case Hash("lsl_z_p_zz"):
9435 sshl(vform, result, zdn, zm, shift_in_ls_byte);
9436 break;
9437 case Hash("lsrr_z_p_zz"):
9438 ushr(vform, result, zm, zdn);
9439 break;
9440 case Hash("lsr_z_p_zz"):
9441 ushr(vform, result, zdn, zm);
9442 break;
9443 case Hash("sqrshl_z_p_zz"):
9444 sshl(vform, result, zdn, zm, shift_in_ls_byte)
9445 .Round(vform)
9446 .SignedSaturate(vform);
9447 break;
9448 case Hash("sqrshlr_z_p_zz"):
9449 sshl(vform, result, zm, zdn, shift_in_ls_byte)
9450 .Round(vform)
9451 .SignedSaturate(vform);
9452 break;
9453 case Hash("sqshl_z_p_zz"):
9454 sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
9455 break;
9456 case Hash("sqshlr_z_p_zz"):
9457 sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
9458 break;
9459 case Hash("srshl_z_p_zz"):
9460 sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9461 break;
9462 case Hash("srshlr_z_p_zz"):
9463 sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9464 break;
9465 case Hash("uqrshl_z_p_zz"):
9466 ushl(vform, result, zdn, zm, shift_in_ls_byte)
9467 .Round(vform)
9468 .UnsignedSaturate(vform);
9469 break;
9470 case Hash("uqrshlr_z_p_zz"):
9471 ushl(vform, result, zm, zdn, shift_in_ls_byte)
9472 .Round(vform)
9473 .UnsignedSaturate(vform);
9474 break;
9475 case Hash("uqshl_z_p_zz"):
9476 ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
9477 break;
9478 case Hash("uqshlr_z_p_zz"):
9479 ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
9480 break;
9481 case Hash("urshl_z_p_zz"):
9482 ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9483 break;
9484 case Hash("urshlr_z_p_zz"):
9485 ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009486 break;
9487 default:
9488 VIXL_UNIMPLEMENTED();
9489 break;
9490 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009491 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009492}
9493
9494void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9495 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009496 VectorFormat vform = instr->GetSVEVectorFormat();
9497 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9498 SimVRegister& zm = ReadVRegister(instr->GetRn());
9499 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9500
9501 SimVRegister result;
9502 Shift shift_op = ASR;
9503
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009504 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9505 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009506 break;
9507 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009508 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009509 break;
9510 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009511 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009512 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009513 default:
9514 VIXL_UNIMPLEMENTED();
9515 break;
9516 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009517 SVEBitwiseShiftHelper(shift_op,
9518 vform,
9519 result,
9520 zdn,
9521 zm,
9522 /* is_wide_elements = */ true);
9523 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009524}
9525
9526void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08009527 SimVRegister& zd = ReadVRegister(instr->GetRd());
9528 SimVRegister& zn = ReadVRegister(instr->GetRn());
9529
9530 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009531 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9532 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009533 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009534 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009535 break;
9536 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009537 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009538 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009539 break;
9540 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08009541 case LSR_z_zw:
9542 shift_op = LSR;
9543 break;
9544 default:
9545 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009546 VIXL_UNIMPLEMENTED();
9547 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08009548 }
9549
9550 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9551 case ASR_z_zi:
9552 case LSL_z_zi:
9553 case LSR_z_zi: {
9554 SimVRegister scratch;
9555 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00009556 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08009557 unsigned lane_size = shift_and_lane_size.second;
9558 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9559 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00009560 int shift_dist = shift_and_lane_size.first;
9561 if (shift_op == LSL) {
9562 // Shift distance is computed differently for LSL. Convert the result.
9563 shift_dist = (8 << lane_size) - shift_dist;
9564 }
9565 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08009566 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9567 break;
9568 }
9569 case ASR_z_zw:
9570 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009571 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009572 SVEBitwiseShiftHelper(shift_op,
9573 instr->GetSVEVectorFormat(),
9574 zd,
9575 zn,
9576 ReadVRegister(instr->GetRm()),
9577 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009578 break;
9579 default:
9580 VIXL_UNIMPLEMENTED();
9581 break;
9582 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009583}
9584
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009585void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00009586 // Although the instructions have a separate encoding class, the lane size is
9587 // encoded in the same way as most other SVE instructions.
9588 VectorFormat vform = instr->GetSVEVectorFormat();
9589
9590 int pattern = instr->GetImmSVEPredicateConstraint();
9591 int count = GetPredicateConstraintLaneCount(vform, pattern);
9592 int multiplier = instr->ExtractBits(19, 16) + 1;
9593
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009594 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009595 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009596 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009597 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009598 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009599 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009600 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009601 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009602 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009603 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009604 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009605 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009606 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009607 default:
9608 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00009609 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009610 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00009611
9612 WriteXRegister(instr->GetRd(),
9613 IncDecN(ReadXRegister(instr->GetRd()),
9614 count * multiplier,
9615 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009616}
9617
9618void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009619 VectorFormat vform = instr->GetSVEVectorFormat();
9620 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9621 VIXL_UNIMPLEMENTED();
9622 }
9623
9624 int pattern = instr->GetImmSVEPredicateConstraint();
9625 int count = GetPredicateConstraintLaneCount(vform, pattern);
9626 int multiplier = instr->ExtractBits(19, 16) + 1;
9627
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009628 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9629 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009630 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009631 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009632 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009633 break;
9634 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009635 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009636 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009637 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009638 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009639 default:
9640 VIXL_UNIMPLEMENTED();
9641 break;
9642 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009643
9644 SimVRegister& zd = ReadVRegister(instr->GetRd());
9645 SimVRegister scratch;
9646 dup_immediate(vform,
9647 scratch,
9648 IncDecN(0,
9649 count * multiplier,
9650 LaneSizeInBitsFromFormat(vform)));
9651 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009652}
9653
9654void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9655 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009656 // Although the instructions have a separate encoding class, the lane size is
9657 // encoded in the same way as most other SVE instructions.
9658 VectorFormat vform = instr->GetSVEVectorFormat();
9659
9660 int pattern = instr->GetImmSVEPredicateConstraint();
9661 int count = GetPredicateConstraintLaneCount(vform, pattern);
9662 int multiplier = instr->ExtractBits(19, 16) + 1;
9663
9664 unsigned width = kXRegSize;
9665 bool is_signed = false;
9666
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009667 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009668 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009669 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009670 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009671 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009672 width = kWRegSize;
9673 VIXL_FALLTHROUGH();
9674 case SQDECB_r_rs_x:
9675 case SQDECD_r_rs_x:
9676 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009677 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009678 is_signed = true;
9679 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009680 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009681 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009682 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009683 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009684 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009685 width = kWRegSize;
9686 VIXL_FALLTHROUGH();
9687 case SQINCB_r_rs_x:
9688 case SQINCD_r_rs_x:
9689 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009690 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009691 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009692 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009693 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009694 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009695 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009696 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009697 width = kWRegSize;
9698 VIXL_FALLTHROUGH();
9699 case UQDECB_r_rs_x:
9700 case UQDECD_r_rs_x:
9701 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009702 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009703 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009704 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009705 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009706 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009707 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009708 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009709 width = kWRegSize;
9710 VIXL_FALLTHROUGH();
9711 case UQINCB_r_rs_x:
9712 case UQINCD_r_rs_x:
9713 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009714 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009715 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009716 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009717 default:
9718 VIXL_UNIMPLEMENTED();
9719 break;
9720 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009721
9722 WriteXRegister(instr->GetRd(),
9723 IncDecN(ReadXRegister(instr->GetRd()),
9724 count * multiplier,
9725 width,
9726 true,
9727 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009728}
9729
9730void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9731 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009732 VectorFormat vform = instr->GetSVEVectorFormat();
9733 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9734 VIXL_UNIMPLEMENTED();
9735 }
9736
9737 int pattern = instr->GetImmSVEPredicateConstraint();
9738 int count = GetPredicateConstraintLaneCount(vform, pattern);
9739 int multiplier = instr->ExtractBits(19, 16) + 1;
9740
9741 SimVRegister& zd = ReadVRegister(instr->GetRd());
9742 SimVRegister scratch;
9743 dup_immediate(vform,
9744 scratch,
9745 IncDecN(0,
9746 count * multiplier,
9747 LaneSizeInBitsFromFormat(vform)));
9748
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009749 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9750 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009751 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009752 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009753 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009754 break;
9755 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009756 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009757 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009758 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009759 break;
9760 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009761 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009762 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009763 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009764 break;
9765 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009766 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009767 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009768 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009769 break;
9770 default:
9771 VIXL_UNIMPLEMENTED();
9772 break;
9773 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009774}
9775
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009776void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009777 switch (instr->Mask(SVEElementCountMask)) {
9778 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009779 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009780 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009781 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00009782 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009783 break;
9784 default:
9785 VIXL_UNIMPLEMENTED();
9786 break;
9787 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00009788
9789 // Although the instructions are separated, the lane size is encoded in the
9790 // same way as most other SVE instructions.
9791 VectorFormat vform = instr->GetSVEVectorFormat();
9792
9793 int pattern = instr->GetImmSVEPredicateConstraint();
9794 int count = GetPredicateConstraintLaneCount(vform, pattern);
9795 int multiplier = instr->ExtractBits(19, 16) + 1;
9796 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009797}
9798
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009799void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009800 VectorFormat vform = instr->GetSVEVectorFormat();
9801 SimVRegister& vdn = ReadVRegister(instr->GetRd());
9802 SimVRegister& zm = ReadVRegister(instr->GetRn());
9803 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9804
Martyn Capewell310a0822020-09-08 20:09:17 +01009805 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9806
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009807 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9808 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009809 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009810 break;
9811 default:
9812 VIXL_UNIMPLEMENTED();
9813 break;
9814 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009815}
9816
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009817void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07009818 VectorFormat vform = instr->GetSVEVectorFormat();
9819 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9820 SimVRegister& zm = ReadVRegister(instr->GetRn());
9821 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9822
Martyn Capewell310a0822020-09-08 20:09:17 +01009823 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
TatWai Chongd316c5e2019-10-16 12:22:10 -07009824
Martyn Capewell310a0822020-09-08 20:09:17 +01009825 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009826 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009827 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009828 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009829 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009830 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009831 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009832 break;
9833 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009834 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009835 break;
9836 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009837 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009838 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009839 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009840 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009841 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009842 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009843 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009844 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009845 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009846 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009847 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009848 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009849 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009850 break;
9851 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009852 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009853 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009854 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009855 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009856 break;
9857 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009858 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009859 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009860 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009861 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009862 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009863 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009864 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009865 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009866 default:
9867 VIXL_UNIMPLEMENTED();
9868 break;
9869 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07009870 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009871}
9872
9873void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9874 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00009875 VectorFormat vform = instr->GetSVEVectorFormat();
9876 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9877 VIXL_UNIMPLEMENTED();
9878 }
9879
9880 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9881 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9882 SimVRegister result;
9883
9884 int i1 = instr->ExtractBit(5);
9885 SimVRegister add_sub_imm, min_max_imm, mul_imm;
9886 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9887 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9888 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9889 dup_immediate(vform, add_sub_imm, i1 ? one : half);
9890 dup_immediate(vform, min_max_imm, i1 ? one : 0);
9891 dup_immediate(vform, mul_imm, i1 ? two : half);
9892
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009893 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9894 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009895 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009896 break;
9897 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009898 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009899 break;
9900 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009901 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009902 break;
9903 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009904 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009905 break;
9906 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009907 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009908 break;
9909 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009910 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009911 break;
9912 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009913 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009914 break;
9915 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009916 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009917 break;
9918 default:
9919 VIXL_UNIMPLEMENTED();
9920 break;
9921 }
Martyn Capewella2fadc22020-01-16 16:09:55 +00009922 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009923}
9924
9925void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009926 VectorFormat vform = instr->GetSVEVectorFormat();
9927 SimVRegister& zd = ReadVRegister(instr->GetRd());
9928 SimVRegister& zm = ReadVRegister(instr->GetRn());
9929
Martyn Capewell310a0822020-09-08 20:09:17 +01009930 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9931
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009932 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009933 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009934 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009935 break;
9936 default:
9937 VIXL_UNIMPLEMENTED();
9938 break;
9939 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009940}
9941
9942void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -07009943 VectorFormat vform = instr->GetSVEVectorFormat();
9944 SimVRegister& zd = ReadVRegister(instr->GetRd());
9945 SimVRegister& zn = ReadVRegister(instr->GetRn());
9946 SimVRegister& zm = ReadVRegister(instr->GetRm());
9947
Martyn Capewell310a0822020-09-08 20:09:17 +01009948 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9949
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009950 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
9951 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009952 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009953 break;
9954 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009955 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009956 break;
9957 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009958 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009959 break;
9960 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009961 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009962 break;
9963 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009964 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009965 break;
9966 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009967 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009968 break;
9969 default:
9970 VIXL_UNIMPLEMENTED();
9971 break;
9972 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009973}
9974
9975void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -08009976 SimPRegister& pd = ReadPRegister(instr->GetPd());
9977 SimVRegister& zn = ReadVRegister(instr->GetRn());
9978 SimVRegister& zm = ReadVRegister(instr->GetRm());
9979 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9980 VectorFormat vform = instr->GetSVEVectorFormat();
9981 SimVRegister result;
9982
Martyn Capewell310a0822020-09-08 20:09:17 +01009983 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9984
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009985 switch (instr->Mask(SVEFPCompareVectorsMask)) {
9986 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009987 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009988 break;
9989 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009990 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009991 break;
9992 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009993 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009994 break;
9995 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009996 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009997 break;
9998 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08009999 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010000 break;
10001 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010002 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010003 break;
10004 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010005 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010006 break;
10007 default:
10008 VIXL_UNIMPLEMENTED();
10009 break;
10010 }
TatWai Chong47c26842020-02-10 01:51:32 -080010011
10012 ExtractFromSimVRegister(vform, pd, result);
10013 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010014}
10015
10016void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -080010017 SimPRegister& pd = ReadPRegister(instr->GetPd());
10018 SimVRegister& zn = ReadVRegister(instr->GetRn());
10019 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10020 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chonge3775132020-02-16 22:13:17 -080010021
Martyn Capewell310a0822020-09-08 20:09:17 +010010022 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10023
10024 SimVRegister result;
TatWai Chonge3775132020-02-16 22:13:17 -080010025 SimVRegister zeros;
10026 dup_immediate(kFormatVnD, zeros, 0);
10027
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010028 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10029 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010030 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010031 break;
10032 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010033 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010034 break;
10035 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010036 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010037 break;
10038 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010039 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010040 break;
10041 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010042 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010043 break;
10044 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010045 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010046 break;
10047 default:
10048 VIXL_UNIMPLEMENTED();
10049 break;
10050 }
TatWai Chonge3775132020-02-16 22:13:17 -080010051
10052 ExtractFromSimVRegister(vform, pd, result);
10053 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010054}
10055
10056void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010057 VectorFormat vform = instr->GetSVEVectorFormat();
10058
10059 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10060 VIXL_UNIMPLEMENTED();
10061 }
10062
10063 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10064 SimVRegister& zm = ReadVRegister(instr->GetRn());
10065 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10066 int rot = instr->ExtractBit(16);
10067
10068 SimVRegister result;
10069
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010070 switch (instr->Mask(SVEFPComplexAdditionMask)) {
10071 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010072 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010073 break;
10074 default:
10075 VIXL_UNIMPLEMENTED();
10076 break;
10077 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010078 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010079}
10080
10081void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +010010082 VectorFormat vform = instr->GetSVEVectorFormat();
10083
10084 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10085 VIXL_UNIMPLEMENTED();
10086 }
10087
10088 SimVRegister& zda = ReadVRegister(instr->GetRd());
10089 SimVRegister& zn = ReadVRegister(instr->GetRn());
10090 SimVRegister& zm = ReadVRegister(instr->GetRm());
10091 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10092 int rot = instr->ExtractBits(14, 13);
10093
10094 SimVRegister result;
10095
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010096 switch (instr->Mask(SVEFPComplexMulAddMask)) {
10097 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +010010098 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010099 break;
10100 default:
10101 VIXL_UNIMPLEMENTED();
10102 break;
10103 }
Martyn Capewell75f1c432020-03-30 09:23:27 +010010104 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010105}
10106
10107void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +010010108 SimVRegister& zda = ReadVRegister(instr->GetRd());
10109 SimVRegister& zn = ReadVRegister(instr->GetRn());
10110 int rot = instr->ExtractBits(11, 10);
10111 unsigned zm_code = instr->GetRm();
10112 int index = -1;
10113 VectorFormat vform, vform_dup;
10114
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010115 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10116 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010117 vform = kFormatVnH;
10118 vform_dup = kFormatVnS;
10119 index = zm_code >> 3;
10120 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010121 break;
10122 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010123 vform = kFormatVnS;
10124 vform_dup = kFormatVnD;
10125 index = zm_code >> 4;
10126 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010127 break;
10128 default:
10129 VIXL_UNIMPLEMENTED();
10130 break;
10131 }
Martyn Capewelle4886e52020-03-30 09:28:52 +010010132
10133 if (index >= 0) {
10134 SimVRegister temp;
10135 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10136 fcmla(vform, zda, zn, temp, zda, rot);
10137 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010138}
10139
Martyn Capewell894962f2020-02-05 15:46:44 +000010140typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10141 LogicVRegister dst,
10142 const LogicVRegister& src);
10143
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010144void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +000010145 VectorFormat vform = instr->GetSVEVectorFormat();
10146 SimVRegister& vd = ReadVRegister(instr->GetRd());
10147 SimVRegister& zn = ReadVRegister(instr->GetRn());
10148 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10149 int lane_size = LaneSizeInBitsFromFormat(vform);
10150
10151 uint64_t inactive_value = 0;
10152 FastReduceFn fn = nullptr;
10153
Martyn Capewell310a0822020-09-08 20:09:17 +010010154 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10155
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010156 switch (instr->Mask(SVEFPFastReductionMask)) {
10157 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010158 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010159 break;
10160 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010161 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10162 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010163 break;
10164 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010165 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10166 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010167 break;
10168 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010169 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10170 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010171 break;
10172 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010173 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10174 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010175 break;
10176 default:
10177 VIXL_UNIMPLEMENTED();
10178 break;
10179 }
Martyn Capewell894962f2020-02-05 15:46:44 +000010180
10181 SimVRegister scratch;
10182 dup_immediate(vform, scratch, inactive_value);
10183 mov_merging(vform, scratch, pg, zn);
10184 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010185}
10186
10187void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +000010188 VectorFormat vform = kFormatUndefined;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010189
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010190 switch (instr->Mask(SVEFPMulIndexMask)) {
10191 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010192 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010193 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010194 case FMUL_z_zzi_h_i3h:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010195 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010196 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010197 break;
10198 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010199 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010200 break;
10201 default:
10202 VIXL_UNIMPLEMENTED();
10203 break;
10204 }
Martyn Capewell50e9f552020-01-07 17:45:03 +000010205
10206 SimVRegister& zd = ReadVRegister(instr->GetRd());
10207 SimVRegister& zn = ReadVRegister(instr->GetRn());
10208 SimVRegister temp;
10209
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010210 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
Martyn Capewell50e9f552020-01-07 17:45:03 +000010211 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010212}
10213
10214void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -080010215 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongf8d29f12020-02-16 22:53:18 -080010216 SimVRegister& zd = ReadVRegister(instr->GetRd());
10217 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10218 SimVRegister result;
10219
Martyn Capewell310a0822020-09-08 20:09:17 +010010220 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10221
TatWai Chongf8d29f12020-02-16 22:53:18 -080010222 if (instr->ExtractBit(15) == 0) {
10223 // Floating-point multiply-accumulate writing addend.
10224 SimVRegister& zm = ReadVRegister(instr->GetRm());
10225 SimVRegister& zn = ReadVRegister(instr->GetRn());
10226
10227 switch (instr->Mask(SVEFPMulAddMask)) {
10228 // zda = zda + zn * zm
10229 case FMLA_z_p_zzz:
10230 fmla(vform, result, zd, zn, zm);
10231 break;
10232 // zda = -zda + -zn * zm
10233 case FNMLA_z_p_zzz:
10234 fneg(vform, result, zd);
10235 fmls(vform, result, result, zn, zm);
10236 break;
10237 // zda = zda + -zn * zm
10238 case FMLS_z_p_zzz:
10239 fmls(vform, result, zd, zn, zm);
10240 break;
10241 // zda = -zda + zn * zm
10242 case FNMLS_z_p_zzz:
10243 fneg(vform, result, zd);
10244 fmla(vform, result, result, zn, zm);
10245 break;
10246 default:
10247 VIXL_UNIMPLEMENTED();
10248 break;
10249 }
10250 } else {
10251 // Floating-point multiply-accumulate writing multiplicand.
10252 SimVRegister& za = ReadVRegister(instr->GetRm());
10253 SimVRegister& zm = ReadVRegister(instr->GetRn());
10254
10255 switch (instr->Mask(SVEFPMulAddMask)) {
10256 // zdn = za + zdn * zm
10257 case FMAD_z_p_zzz:
10258 fmla(vform, result, za, zd, zm);
10259 break;
10260 // zdn = -za + -zdn * zm
10261 case FNMAD_z_p_zzz:
10262 fneg(vform, result, za);
10263 fmls(vform, result, result, zd, zm);
10264 break;
10265 // zdn = za + -zdn * zm
10266 case FMSB_z_p_zzz:
10267 fmls(vform, result, za, zd, zm);
10268 break;
10269 // zdn = -za + zdn * zm
10270 case FNMSB_z_p_zzz:
10271 fneg(vform, result, za);
10272 fmla(vform, result, result, zd, zm);
10273 break;
10274 default:
10275 VIXL_UNIMPLEMENTED();
10276 break;
10277 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010278 }
TatWai Chongf8d29f12020-02-16 22:53:18 -080010279
10280 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010281}
10282
10283void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010284 VectorFormat vform = kFormatUndefined;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010285
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010286 switch (instr->Mask(SVEFPMulAddIndexMask)) {
10287 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010288 case FMLS_z_zzzi_d:
10289 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010290 break;
10291 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010292 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010293 vform = kFormatVnS;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010294 break;
10295 case FMLA_z_zzzi_h:
10296 case FMLS_z_zzzi_h:
10297 case FMLA_z_zzzi_h_i3h:
10298 case FMLS_z_zzzi_h_i3h:
10299 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010300 break;
10301 default:
10302 VIXL_UNIMPLEMENTED();
10303 break;
10304 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010305
10306 SimVRegister& zd = ReadVRegister(instr->GetRd());
10307 SimVRegister& zn = ReadVRegister(instr->GetRn());
10308 SimVRegister temp;
10309
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010310 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010311 if (instr->ExtractBit(10) == 1) {
10312 fmls(vform, zd, zd, zn, temp);
10313 } else {
10314 fmla(vform, zd, zd, zn, temp);
10315 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010316}
10317
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010318void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -080010319 SimVRegister& zd = ReadVRegister(instr->GetRd());
10320 SimVRegister& zn = ReadVRegister(instr->GetRn());
10321 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10322 int dst_data_size;
10323 int src_data_size;
10324
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010325 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010326 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010327 case FCVTZU_z_p_z_d2w:
10328 dst_data_size = kSRegSize;
10329 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010330 break;
10331 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010332 case FCVTZU_z_p_z_d2x:
10333 dst_data_size = kDRegSize;
10334 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010335 break;
10336 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010337 case FCVTZU_z_p_z_fp162h:
10338 dst_data_size = kHRegSize;
10339 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010340 break;
10341 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010342 case FCVTZU_z_p_z_fp162w:
10343 dst_data_size = kSRegSize;
10344 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010345 break;
10346 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010347 case FCVTZU_z_p_z_fp162x:
10348 dst_data_size = kDRegSize;
10349 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010350 break;
10351 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010352 case FCVTZU_z_p_z_s2w:
10353 dst_data_size = kSRegSize;
10354 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010355 break;
10356 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010357 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010358 dst_data_size = kDRegSize;
10359 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010360 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010361 default:
10362 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -080010363 dst_data_size = 0;
10364 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010365 break;
10366 }
TatWai Chongdb7437c2020-01-09 17:44:10 -080010367
10368 VectorFormat vform =
10369 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -080010370
10371 if (instr->ExtractBit(16) == 0) {
10372 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10373 } else {
10374 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10375 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010376}
10377
10378void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -080010379 SimVRegister& zd = ReadVRegister(instr->GetRd());
10380 SimVRegister& zn = ReadVRegister(instr->GetRn());
10381 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10382 int dst_data_size;
10383 int src_data_size;
10384
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010385 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010386 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010387 dst_data_size = kHRegSize;
10388 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010389 break;
10390 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010391 dst_data_size = kSRegSize;
10392 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010393 break;
10394 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010395 dst_data_size = kDRegSize;
10396 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010397 break;
10398 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010399 dst_data_size = kSRegSize;
10400 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010401 break;
10402 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010403 dst_data_size = kDRegSize;
10404 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010405 break;
10406 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010407 dst_data_size = kHRegSize;
10408 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010409 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010410 default:
10411 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -080010412 dst_data_size = 0;
10413 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010414 break;
10415 }
TatWai Chong2cb1b612020-03-04 23:51:21 -080010416 VectorFormat vform =
10417 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10418
10419 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010420}
10421
10422void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010423 SimVRegister& zd = ReadVRegister(instr->GetRd());
10424 SimVRegister& zn = ReadVRegister(instr->GetRn());
10425 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10426 VectorFormat vform = instr->GetSVEVectorFormat();
10427 SimVRegister result;
10428
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010429 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010430 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010431 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010432 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010433 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -080010434 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010435 break;
10436 default:
10437 VIXL_UNIMPLEMENTED();
10438 break;
10439 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010440 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010441}
10442
10443void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010444 SimVRegister& zd = ReadVRegister(instr->GetRd());
10445 SimVRegister& zn = ReadVRegister(instr->GetRn());
10446 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10447 VectorFormat vform = instr->GetSVEVectorFormat();
10448 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10449 bool exact_exception = false;
10450
Martyn Capewell310a0822020-09-08 20:09:17 +010010451 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10452
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010453 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010454 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010455 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010456 break;
10457 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010458 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010459 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010460 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010461 break;
10462 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010463 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010464 break;
10465 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010466 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010467 break;
10468 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010469 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010470 break;
10471 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010472 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010473 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010474 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010475 VIXL_UNIMPLEMENTED();
10476 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010477 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010478
10479 SimVRegister result;
10480 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10481 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010482}
10483
10484void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -080010485 SimVRegister& zd = ReadVRegister(instr->GetRd());
10486 SimVRegister& zn = ReadVRegister(instr->GetRn());
10487 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10488 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10489 int dst_data_size;
10490 int src_data_size;
10491
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010492 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010493 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010494 case UCVTF_z_p_z_h2fp16:
10495 dst_data_size = kHRegSize;
10496 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010497 break;
10498 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010499 case UCVTF_z_p_z_w2d:
10500 dst_data_size = kDRegSize;
10501 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010502 break;
10503 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010504 case UCVTF_z_p_z_w2fp16:
10505 dst_data_size = kHRegSize;
10506 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010507 break;
10508 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010509 case UCVTF_z_p_z_w2s:
10510 dst_data_size = kSRegSize;
10511 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010512 break;
10513 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010514 case UCVTF_z_p_z_x2d:
10515 dst_data_size = kDRegSize;
10516 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010517 break;
10518 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010519 case UCVTF_z_p_z_x2fp16:
10520 dst_data_size = kHRegSize;
10521 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010522 break;
10523 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010524 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010525 dst_data_size = kSRegSize;
10526 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010527 break;
10528 default:
10529 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -080010530 dst_data_size = 0;
10531 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010532 break;
10533 }
TatWai Chong31cd6a02020-01-10 13:03:26 -080010534
10535 VectorFormat vform =
10536 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10537
10538 if (instr->ExtractBit(16) == 0) {
10539 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10540 } else {
10541 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10542 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010543}
10544
10545void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +000010546 VectorFormat vform = instr->GetSVEVectorFormat();
10547 SimVRegister& zd = ReadVRegister(instr->GetRd());
10548 SimVRegister& zn = ReadVRegister(instr->GetRn());
10549 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10550
Martyn Capewell310a0822020-09-08 20:09:17 +010010551 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10552
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010553 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10554 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010555 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010556 break;
10557 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010558 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010559 break;
10560 default:
10561 VIXL_UNIMPLEMENTED();
10562 break;
10563 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010564}
10565
10566void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010567 VectorFormat vform = instr->GetSVEVectorFormat();
10568 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10569
10570 int count = CountActiveLanes(vform, pg);
10571
10572 if (instr->ExtractBit(11) == 0) {
10573 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10574 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10575 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010576 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010577 break;
10578 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010579 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010580 break;
10581 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010582 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010583 break;
10584 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010585 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010586 break;
10587 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010588 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010589 break;
10590 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010591 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010592 break;
10593 default:
10594 VIXL_UNIMPLEMENTED();
10595 break;
10596 }
10597 } else {
10598 bool is_saturating = (instr->ExtractBit(18) == 0);
10599 bool decrement =
10600 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10601 bool is_signed = (instr->ExtractBit(16) == 0);
10602 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10603 unsigned width = sf ? kXRegSize : kWRegSize;
10604
10605 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10606 case DECP_r_p_r:
10607 case INCP_r_p_r:
10608 case SQDECP_r_p_r_sx:
10609 case SQDECP_r_p_r_x:
10610 case SQINCP_r_p_r_sx:
10611 case SQINCP_r_p_r_x:
10612 case UQDECP_r_p_r_uw:
10613 case UQDECP_r_p_r_x:
10614 case UQINCP_r_p_r_uw:
10615 case UQINCP_r_p_r_x:
10616 WriteXRegister(instr->GetRd(),
10617 IncDecN(ReadXRegister(instr->GetRd()),
10618 decrement ? -count : count,
10619 width,
10620 is_saturating,
10621 is_signed));
10622 break;
10623 default:
10624 VIXL_UNIMPLEMENTED();
10625 break;
10626 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010627 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010628}
10629
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010630uint64_t Simulator::IncDecN(uint64_t acc,
10631 int64_t delta,
10632 unsigned n,
10633 bool is_saturating,
10634 bool is_signed) {
10635 VIXL_ASSERT(n <= 64);
10636 VIXL_ASSERT(IsIntN(n, delta));
10637
10638 uint64_t sign_mask = UINT64_C(1) << (n - 1);
10639 uint64_t mask = GetUintMask(n);
10640
10641 acc &= mask; // Ignore initial accumulator high bits.
10642 uint64_t result = (acc + delta) & mask;
10643
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010644 bool result_negative = ((result & sign_mask) != 0);
10645
10646 if (is_saturating) {
10647 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +000010648 bool acc_negative = ((acc & sign_mask) != 0);
10649 bool delta_negative = delta < 0;
10650
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010651 // If the signs of the operands are the same, but different from the
10652 // result, there was an overflow.
10653 if ((acc_negative == delta_negative) &&
10654 (acc_negative != result_negative)) {
10655 if (result_negative) {
10656 // Saturate to [..., INT<n>_MAX].
10657 result_negative = false;
10658 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
10659 } else {
10660 // Saturate to [INT<n>_MIN, ...].
10661 result_negative = true;
10662 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
10663 }
10664 }
10665 } else {
10666 if ((delta < 0) && (result > acc)) {
10667 // Saturate to [0, ...].
10668 result = 0;
10669 } else if ((delta > 0) && (result < acc)) {
10670 // Saturate to [..., UINT<n>_MAX].
10671 result = mask;
10672 }
10673 }
10674 }
10675
10676 // Sign-extend if necessary.
10677 if (result_negative && is_signed) result |= ~mask;
10678
10679 return result;
10680}
10681
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010682void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010683 VectorFormat vform = instr->GetSVEVectorFormat();
10684 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010685 switch (instr->Mask(SVEIndexGenerationMask)) {
10686 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010687 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010688 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010689 case INDEX_z_rr: {
10690 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10691 : instr->ExtractSignedBits(9, 5);
10692 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10693 : instr->ExtractSignedBits(20, 16);
10694 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010695 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010696 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010697 default:
10698 VIXL_UNIMPLEMENTED();
10699 break;
10700 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010701}
10702
10703void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -070010704 VectorFormat vform = instr->GetSVEVectorFormat();
10705 SimVRegister& zd = ReadVRegister(instr->GetRd());
10706 SimVRegister& zn = ReadVRegister(instr->GetRn());
10707 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010708 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10709 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010710 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010711 break;
10712 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010713 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010714 break;
10715 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010716 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010717 break;
10718 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010719 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010720 break;
10721 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010722 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010723 break;
10724 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010725 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010726 break;
10727 default:
10728 VIXL_UNIMPLEMENTED();
10729 break;
10730 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010731}
10732
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010733void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010734 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -070010735 VectorFormat vform = instr->GetSVEVectorFormat();
10736 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10737 SimVRegister& zm = ReadVRegister(instr->GetRn());
10738 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10739 SimVRegister result;
10740
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010741 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010742 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010743 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010744 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010745 case SUBR_z_p_zz:
10746 sub(vform, result, zm, zdn);
10747 break;
10748 case SUB_z_p_zz:
10749 sub(vform, result, zdn, zm);
10750 break;
10751 default:
10752 VIXL_UNIMPLEMENTED();
10753 break;
10754 }
10755 mov_merging(vform, zdn, pg, result);
10756}
10757
10758void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10759 VectorFormat vform = instr->GetSVEVectorFormat();
10760 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10761 SimVRegister& zm = ReadVRegister(instr->GetRn());
10762 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10763 SimVRegister result;
10764
10765 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010766 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010767 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010768 break;
10769 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010770 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010771 break;
10772 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010773 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010774 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010775 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010776 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010777 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010778 default:
10779 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010780 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010781 }
10782 mov_merging(vform, zdn, pg, result);
10783}
10784
10785void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10786 VectorFormat vform = instr->GetSVEVectorFormat();
10787 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10788 SimVRegister& zm = ReadVRegister(instr->GetRn());
10789 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10790 SimVRegister result;
10791
10792 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10793 case MUL_z_p_zz:
10794 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010795 break;
10796 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010797 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010798 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010799 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010800 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010801 break;
10802 default:
10803 VIXL_UNIMPLEMENTED();
10804 break;
10805 }
TatWai Chong13634762019-07-16 16:20:45 -070010806 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010807}
10808
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010809void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10810 const Instruction* instr) {
10811 VectorFormat vform = instr->GetSVEVectorFormat();
10812 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10813 SimVRegister& zm = ReadVRegister(instr->GetRn());
10814 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10815 SimVRegister result;
10816
10817 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10818 case SABD_z_p_zz:
10819 absdiff(vform, result, zdn, zm, true);
10820 break;
10821 case SMAX_z_p_zz:
10822 smax(vform, result, zdn, zm);
10823 break;
10824 case SMIN_z_p_zz:
10825 smin(vform, result, zdn, zm);
10826 break;
10827 case UABD_z_p_zz:
10828 absdiff(vform, result, zdn, zm, false);
10829 break;
10830 case UMAX_z_p_zz:
10831 umax(vform, result, zdn, zm);
10832 break;
10833 case UMIN_z_p_zz:
10834 umin(vform, result, zdn, zm);
10835 break;
10836 default:
10837 VIXL_UNIMPLEMENTED();
10838 break;
10839 }
10840 mov_merging(vform, zdn, pg, result);
10841}
10842
10843void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10844 VectorFormat vform = instr->GetSVEVectorFormat();
10845 SimVRegister& zd = ReadVRegister(instr->GetRd());
10846 SimVRegister scratch;
10847
10848 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10849 case MUL_z_zi:
10850 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10851 mul(vform, zd, zd, scratch);
10852 break;
10853 default:
10854 VIXL_UNIMPLEMENTED();
10855 break;
10856 }
10857}
10858
10859void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10860 VectorFormat vform = instr->GetSVEVectorFormat();
10861 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10862 SimVRegister& zm = ReadVRegister(instr->GetRn());
10863 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10864 SimVRegister result;
10865
10866 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10867
10868 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10869 case SDIVR_z_p_zz:
10870 sdiv(vform, result, zm, zdn);
10871 break;
10872 case SDIV_z_p_zz:
10873 sdiv(vform, result, zdn, zm);
10874 break;
10875 case UDIVR_z_p_zz:
10876 udiv(vform, result, zm, zdn);
10877 break;
10878 case UDIV_z_p_zz:
10879 udiv(vform, result, zdn, zm);
10880 break;
10881 default:
10882 VIXL_UNIMPLEMENTED();
10883 break;
10884 }
10885 mov_merging(vform, zdn, pg, result);
10886}
10887
10888void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10889 VectorFormat vform = instr->GetSVEVectorFormat();
10890 SimVRegister& zd = ReadVRegister(instr->GetRd());
10891 SimVRegister scratch;
10892
10893 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10894 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10895
10896 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10897 case SMAX_z_zi:
10898 dup_immediate(vform, scratch, signed_imm);
10899 smax(vform, zd, zd, scratch);
10900 break;
10901 case SMIN_z_zi:
10902 dup_immediate(vform, scratch, signed_imm);
10903 smin(vform, zd, zd, scratch);
10904 break;
10905 case UMAX_z_zi:
10906 dup_immediate(vform, scratch, unsigned_imm);
10907 umax(vform, zd, zd, scratch);
10908 break;
10909 case UMIN_z_zi:
10910 dup_immediate(vform, scratch, unsigned_imm);
10911 umin(vform, zd, zd, scratch);
10912 break;
10913 default:
10914 VIXL_UNIMPLEMENTED();
10915 break;
10916 }
10917}
10918
10919void Simulator::VisitSVEIntCompareScalarCountAndLimit(
10920 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -070010921 unsigned rn_code = instr->GetRn();
10922 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010923 SimPRegister& pd = ReadPRegister(instr->GetPd());
10924 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongc844bb22019-06-10 15:32:53 -070010925
Martyn Capewellf0844012020-10-23 16:38:26 +010010926 bool is_64_bit = instr->ExtractBit(12) == 1;
10927 int rsize = is_64_bit ? kXRegSize : kWRegSize;
10928 uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
10929
10930 uint64_t usrc1 = ReadXRegister(rn_code);
10931 int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
10932 uint64_t usrc2 = ssrc2 & mask;
10933
10934 bool reverse = (form_hash_ == Hash("whilege_p_p_rr")) ||
10935 (form_hash_ == Hash("whilegt_p_p_rr")) ||
10936 (form_hash_ == Hash("whilehi_p_p_rr")) ||
10937 (form_hash_ == Hash("whilehs_p_p_rr"));
10938
10939 int lane_count = LaneCountFromFormat(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010940 bool last = true;
Martyn Capewellf0844012020-10-23 16:38:26 +010010941 for (int i = 0; i < lane_count; i++) {
10942 usrc1 &= mask;
10943 int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
10944
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010945 bool cond = false;
Martyn Capewellf0844012020-10-23 16:38:26 +010010946 switch (form_hash_) {
10947 case Hash("whilele_p_p_rr"):
10948 cond = ssrc1 <= ssrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070010949 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010950 case Hash("whilelo_p_p_rr"):
10951 cond = usrc1 < usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010952 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010953 case Hash("whilels_p_p_rr"):
10954 cond = usrc1 <= usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010955 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010956 case Hash("whilelt_p_p_rr"):
10957 cond = ssrc1 < ssrc2;
10958 break;
10959 case Hash("whilege_p_p_rr"):
10960 cond = ssrc1 >= ssrc2;
10961 break;
10962 case Hash("whilegt_p_p_rr"):
10963 cond = ssrc1 > ssrc2;
10964 break;
10965 case Hash("whilehi_p_p_rr"):
10966 cond = usrc1 > usrc2;
10967 break;
10968 case Hash("whilehs_p_p_rr"):
10969 cond = usrc1 >= usrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070010970 break;
10971 default:
TatWai Chongc844bb22019-06-10 15:32:53 -070010972 VIXL_UNIMPLEMENTED();
10973 break;
10974 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010975 last = last && cond;
10976 LogicPRegister dst(pd);
Martyn Capewellf0844012020-10-23 16:38:26 +010010977 int lane = reverse ? ((lane_count - 1) - i) : i;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010978 dst.SetActive(vform, lane, last);
Martyn Capewellf0844012020-10-23 16:38:26 +010010979 usrc1 += reverse ? -1 : 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010980 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010981
10982 PredTest(vform, GetPTrue(), pd);
10983 LogSystemRegister(NZCV);
10984}
10985
10986void Simulator::VisitSVEConditionallyTerminateScalars(
10987 const Instruction* instr) {
10988 unsigned rn_code = instr->GetRn();
10989 unsigned rm_code = instr->GetRm();
10990 bool is_64_bit = instr->ExtractBit(22) == 1;
10991 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
10992 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
10993 bool term;
10994 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
10995 case CTERMEQ_rr:
10996 term = src1 == src2;
10997 break;
10998 case CTERMNE_rr:
10999 term = src1 != src2;
11000 break;
11001 default:
11002 term = false;
11003 VIXL_UNIMPLEMENTED();
11004 break;
11005 }
11006 ReadNzcv().SetN(term ? 1 : 0);
11007 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -070011008 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011009}
11010
11011void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011012 bool commute_inputs = false;
11013 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011014 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11015 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011016 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011017 break;
11018 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011019 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011020 break;
11021 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011022 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011023 break;
11024 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011025 cond = ge;
11026 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011027 break;
11028 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011029 cond = gt;
11030 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011031 break;
11032 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011033 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011034 break;
11035 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011036 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011037 VIXL_UNIMPLEMENTED();
11038 break;
11039 }
TatWai Chong302729c2019-06-14 16:18:51 -070011040
11041 VectorFormat vform = instr->GetSVEVectorFormat();
11042 SimVRegister src2;
11043 dup_immediate(vform,
11044 src2,
11045 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11046 SVEIntCompareVectorsHelper(cond,
11047 vform,
11048 ReadPRegister(instr->GetPd()),
11049 ReadPRegister(instr->GetPgLow8()),
11050 commute_inputs ? src2
11051 : ReadVRegister(instr->GetRn()),
11052 commute_inputs ? ReadVRegister(instr->GetRn())
11053 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011054}
11055
11056void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011057 bool commute_inputs = false;
11058 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011059 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11060 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011061 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011062 break;
11063 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011064 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011065 break;
11066 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011067 cond = hi;
11068 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011069 break;
11070 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011071 cond = hs;
11072 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011073 break;
11074 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011075 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011076 VIXL_UNIMPLEMENTED();
11077 break;
11078 }
TatWai Chong302729c2019-06-14 16:18:51 -070011079
11080 VectorFormat vform = instr->GetSVEVectorFormat();
11081 SimVRegister src2;
11082 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11083 SVEIntCompareVectorsHelper(cond,
11084 vform,
11085 ReadPRegister(instr->GetPd()),
11086 ReadPRegister(instr->GetPgLow8()),
11087 commute_inputs ? src2
11088 : ReadVRegister(instr->GetRn()),
11089 commute_inputs ? ReadVRegister(instr->GetRn())
11090 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011091}
11092
11093void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -070011094 Instr op = instr->Mask(SVEIntCompareVectorsMask);
11095 bool is_wide_elements = false;
11096 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011097 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -070011098 case CMPGE_p_p_zw:
11099 case CMPGT_p_p_zw:
11100 case CMPHI_p_p_zw:
11101 case CMPHS_p_p_zw:
11102 case CMPLE_p_p_zw:
11103 case CMPLO_p_p_zw:
11104 case CMPLS_p_p_zw:
11105 case CMPLT_p_p_zw:
11106 case CMPNE_p_p_zw:
11107 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011108 break;
TatWai Chong96713fe2019-06-04 16:39:37 -070011109 }
11110
TatWai Chong302729c2019-06-14 16:18:51 -070011111 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -070011112 switch (op) {
11113 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011114 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011115 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011116 break;
11117 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011118 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011119 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011120 break;
11121 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011122 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011123 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011124 break;
11125 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011126 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011127 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011128 break;
11129 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011130 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011131 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011132 break;
11133 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011134 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011135 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -070011136 break;
11137 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011138 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -070011139 break;
11140 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011141 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -070011142 break;
11143 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011144 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -070011145 break;
11146 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011147 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011148 break;
11149 default:
11150 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -070011151 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011152 break;
11153 }
TatWai Chong96713fe2019-06-04 16:39:37 -070011154
TatWai Chong302729c2019-06-14 16:18:51 -070011155 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -070011156 instr->GetSVEVectorFormat(),
11157 ReadPRegister(instr->GetPd()),
11158 ReadPRegister(instr->GetPgLow8()),
11159 ReadVRegister(instr->GetRn()),
11160 ReadVRegister(instr->GetRm()),
11161 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011162}
11163
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011164void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011165 VectorFormat vform = instr->GetSVEVectorFormat();
11166 SimVRegister& zd = ReadVRegister(instr->GetRd());
11167 SimVRegister& zn = ReadVRegister(instr->GetRn());
11168
11169 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11170 (vform == kFormatVnD));
11171
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011172 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011173 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +000011174 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011175 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011176 default:
11177 VIXL_UNIMPLEMENTED();
11178 break;
11179 }
11180}
11181
11182void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011183 VectorFormat vform = instr->GetSVEVectorFormat();
11184 SimVRegister& zd = ReadVRegister(instr->GetRd());
11185 SimVRegister& zn = ReadVRegister(instr->GetRn());
11186 SimVRegister& zm = ReadVRegister(instr->GetRm());
11187
11188 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11189 (vform == kFormatVnD));
11190
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011191 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011192 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +000011193 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011194 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011195 default:
11196 VIXL_UNIMPLEMENTED();
11197 break;
11198 }
11199}
11200
11201void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11202 const Instruction* instr) {
11203 SimVRegister& zd = ReadVRegister(instr->GetRd());
11204 SimVRegister& zn = ReadVRegister(instr->GetRn());
11205
11206 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011207 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011208 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11209 // Record the movprfx, so the next ExecuteInstruction() can check it.
11210 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011211 break;
11212 default:
11213 VIXL_UNIMPLEMENTED();
11214 break;
11215 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011216}
11217
11218void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +010011219 VectorFormat vform = instr->GetSVEVectorFormat();
11220
11221 SimVRegister& zd = ReadVRegister(instr->GetRd());
11222 SimVRegister& zm = ReadVRegister(instr->GetRm());
11223
11224 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011225 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011226 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011227 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011228 break;
11229 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011230 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011231 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011232 case MAD_z_p_zzz:
11233 // 'za' is encoded in 'Rn'.
11234 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011235 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011236 case MSB_z_p_zzz: {
11237 // 'za' is encoded in 'Rn'.
11238 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11239 break;
11240 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011241 default:
11242 VIXL_UNIMPLEMENTED();
11243 break;
11244 }
Jacob Bramley22023df2019-05-14 17:55:43 +010011245 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011246}
11247
11248void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011249 VectorFormat vform = instr->GetSVEVectorFormat();
11250 SimVRegister& zda = ReadVRegister(instr->GetRd());
11251 SimVRegister& zn = ReadVRegister(instr->GetRn());
11252 SimVRegister& zm = ReadVRegister(instr->GetRm());
11253
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011254 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
11255 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011256 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011257 break;
11258 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011259 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011260 break;
11261 default:
11262 VIXL_UNIMPLEMENTED();
11263 break;
11264 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011265}
11266
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011267void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011268 VectorFormat vform = instr->GetSVEVectorFormat();
11269 SimVRegister& zn = ReadVRegister(instr->GetRn());
11270 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11271 SimVRegister& zd = ReadVRegister(instr->GetRd());
11272
11273 switch (instr->Mask(SVEMovprfxMask)) {
11274 case MOVPRFX_z_p_z:
11275 if (instr->ExtractBit(16)) {
11276 mov_merging(vform, zd, pg, zn);
11277 } else {
11278 mov_zeroing(vform, zd, pg, zn);
11279 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011280
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011281 // Record the movprfx, so the next ExecuteInstruction() can check it.
11282 movprfx_ = instr;
11283 break;
11284 default:
11285 VIXL_UNIMPLEMENTED();
11286 break;
11287 }
11288}
11289
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011290void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011291 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +010011292 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011293 SimVRegister& zn = ReadVRegister(instr->GetRn());
11294 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11295
11296 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11297 switch (instr->Mask(SVEIntReductionLogicalMask)) {
11298 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011299 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011300 break;
11301 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011302 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011303 break;
11304 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011305 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011306 break;
11307 default:
11308 VIXL_UNIMPLEMENTED();
11309 break;
11310 }
11311 } else {
11312 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011313 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011314 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011315 break;
11316 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011317 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011318 break;
11319 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011320 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011321 break;
11322 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011323 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011324 break;
11325 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011326 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011327 break;
11328 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011329 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011330 break;
11331 default:
11332 VIXL_UNIMPLEMENTED();
11333 break;
11334 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011335 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011336}
11337
11338void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011339 VectorFormat vform = instr->GetSVEVectorFormat();
11340 SimVRegister& zn = ReadVRegister(instr->GetRn());
11341
11342 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011343 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11344 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011345 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011346 break;
11347 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011348 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011349 break;
11350 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011351 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011352 break;
11353 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011354 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011355 break;
11356 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011357 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011358 break;
11359 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011360 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011361 break;
11362 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011363 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011364 break;
11365 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011366 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011367 break;
11368 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011369 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011370 break;
11371 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011372 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011373 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011374 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011375 break;
11376 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011377 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011378 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011379 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011380 break;
11381 default:
11382 VIXL_UNIMPLEMENTED();
11383 break;
11384 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011385
11386 SimVRegister& zd = ReadVRegister(instr->GetRd());
11387 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11388 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011389}
11390
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011391void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011392 // There is only one instruction in this group.
11393 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11394
11395 VectorFormat vform = instr->GetSVEVectorFormat();
11396 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11397 SimVRegister& zd = ReadVRegister(instr->GetRd());
11398
Martyn Capewell310a0822020-09-08 20:09:17 +010011399 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11400
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011401 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011402 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011403 case FCPY_z_p_i: {
11404 int imm8 = instr->ExtractBits(12, 5);
11405 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11406 Instruction::Imm8ToFP64(imm8));
11407 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011408 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011409 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011410 default:
11411 VIXL_UNIMPLEMENTED();
11412 break;
11413 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011414 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011415}
11416
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011417void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11418 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +010011419 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010011420 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +010011421 SimVRegister scratch;
11422
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011423 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11424 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011425
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011426 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011427 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011428 add_uint(vform, zd, zd, imm);
11429 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011430 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011431 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11432 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011433 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011434 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11435 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011436 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011437 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +010011438 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011439 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011440 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011441 sub_uint(vform, zd, zd, imm);
11442 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011443 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011444 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11445 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011446 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011447 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11448 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011449 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011450 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011451 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011452}
TatWai Chong6995bfd2019-09-26 10:48:05 +010011453
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011454void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11455 SimVRegister& zd = ReadVRegister(instr->GetRd());
11456
Martyn Capewell8ed83522020-08-11 16:19:43 +010011457 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011458 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +010011459 int shift = instr->ExtractBit(13) * 8;
11460 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011461
11462 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11463 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +010011464 // The encoding of byte-sized lanes with lsl #8 is undefined.
11465 if ((format == kFormatVnB) && (shift == 8)) {
11466 VIXL_UNIMPLEMENTED();
11467 } else {
11468 dup_immediate(format, zd, imm);
11469 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011470 break;
11471 default:
11472 VIXL_UNIMPLEMENTED();
11473 break;
11474 }
11475}
11476
11477void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11478 VectorFormat vform = instr->GetSVEVectorFormat();
11479 SimVRegister& zd = ReadVRegister(instr->GetRd());
11480
11481 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011482 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +010011483 switch (vform) {
11484 case kFormatVnH:
11485 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11486 break;
11487 case kFormatVnS:
11488 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11489 break;
11490 case kFormatVnD:
11491 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11492 break;
11493 default:
11494 VIXL_UNIMPLEMENTED();
11495 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011496 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011497 default:
11498 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011499 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011500 }
11501}
11502
11503void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11504 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011505 switch (instr->Mask(
11506 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11507 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011508 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011509 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011510 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011511 break;
11512 default:
11513 VIXL_UNIMPLEMENTED();
11514 break;
11515 }
TatWai Chong113d9192020-05-19 01:02:36 -070011516
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011517 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11518 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011519}
11520
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011521void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011522 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011523 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11524 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011525 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011526 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011527 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011528 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011529 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011530 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011531 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011532 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011533 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011534 break;
11535 default:
11536 VIXL_UNIMPLEMENTED();
11537 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011538 }
TatWai Chong113d9192020-05-19 01:02:36 -070011539
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011540 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11541 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011542}
11543
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011544void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11545 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011546 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11547 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011548 VIXL_UNIMPLEMENTED();
11549 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011550 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011551 VIXL_UNIMPLEMENTED();
11552 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011553 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011554 VIXL_UNIMPLEMENTED();
11555 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011556 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011557 VIXL_UNIMPLEMENTED();
11558 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011559 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011560 VIXL_UNIMPLEMENTED();
11561 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011562 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011563 VIXL_UNIMPLEMENTED();
11564 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011565 case LDFF1H_z_p_ai_s:
11566 VIXL_UNIMPLEMENTED();
11567 break;
11568 case LDFF1SB_z_p_ai_s:
11569 VIXL_UNIMPLEMENTED();
11570 break;
11571 case LDFF1SH_z_p_ai_s:
11572 VIXL_UNIMPLEMENTED();
11573 break;
11574 case LDFF1W_z_p_ai_s:
11575 VIXL_UNIMPLEMENTED();
11576 break;
11577 default:
11578 VIXL_UNIMPLEMENTED();
11579 break;
11580 }
11581}
11582
11583void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11584 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011585 switch (
11586 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11587 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011588 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011589 break;
11590 default:
11591 VIXL_UNIMPLEMENTED();
11592 break;
11593 }
TatWai Chong113d9192020-05-19 01:02:36 -070011594
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011595 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11596 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011597}
11598
11599void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11600 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011601 switch (
11602 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011603 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011604 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011605 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011606 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011607 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011608 break;
11609 default:
11610 VIXL_UNIMPLEMENTED();
11611 break;
11612 }
11613}
11614
11615void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11616 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011617 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011618 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011619 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011620 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011621 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011622 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011623 break;
11624 default:
11625 VIXL_UNIMPLEMENTED();
11626 break;
11627 }
11628}
11629
11630void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11631 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011632 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011633 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011634 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011635 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011636 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011637 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011638 break;
11639 default:
11640 VIXL_UNIMPLEMENTED();
11641 break;
11642 }
11643}
11644
11645void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11646 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011647 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011648 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011649 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011650 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011651 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011652 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +010011653 if (instr->GetRm() == kZeroRegCode) {
11654 VIXL_UNIMPLEMENTED();
11655 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011656 break;
11657 default:
11658 VIXL_UNIMPLEMENTED();
11659 break;
11660 }
11661}
11662
11663void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -070011664 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011665 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011666 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -070011667 case LD1RB_z_p_bi_u16:
11668 case LD1RB_z_p_bi_u32:
11669 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011670 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011671 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011672 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -070011673 case LD1RW_z_p_bi_u32:
11674 case LD1RW_z_p_bi_u64:
11675 case LD1RD_z_p_bi_u64:
11676 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011677 break;
11678 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011679 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011680 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011681 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011682 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011683 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -070011684 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011685 break;
11686 default:
TatWai Chong85e15102020-05-04 21:00:40 -070011687 // This encoding group is complete, so no other values should be possible.
11688 VIXL_UNREACHABLE();
11689 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011690 break;
11691 }
TatWai Chong85e15102020-05-04 21:00:40 -070011692
11693 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11694 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11695 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11696 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11697 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11698 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11699 VectorFormat unpack_vform =
11700 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11701 SimVRegister temp;
11702 ld1r(vform, unpack_vform, temp, base, is_signed);
11703 mov_zeroing(vform,
11704 ReadVRegister(instr->GetRt()),
11705 ReadPRegister(instr->GetPgLow8()),
11706 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011707}
11708
11709void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11710 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11711 case LDR_p_bi: {
11712 SimPRegister& pt = ReadPRegister(instr->GetPt());
11713 int pl = GetPredicateLengthInBytes();
11714 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11715 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11716 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11717 for (int i = 0; i < pl; i++) {
11718 pt.Insert(i, Memory::Read<uint8_t>(address + i));
11719 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011720 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011721 break;
11722 }
11723 default:
11724 VIXL_UNIMPLEMENTED();
11725 break;
11726 }
11727}
11728
11729void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011730 switch (instr->Mask(SVELoadVectorRegisterMask)) {
11731 case LDR_z_bi: {
11732 SimVRegister& zt = ReadVRegister(instr->GetRt());
11733 int vl = GetVectorLengthInBytes();
11734 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11735 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11736 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11737 for (int i = 0; i < vl; i++) {
11738 zt.Insert(i, Memory::Read<uint8_t>(address + i));
11739 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011740 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011741 break;
11742 }
11743 default:
11744 VIXL_UNIMPLEMENTED();
11745 break;
11746 }
11747}
11748
11749void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11750 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011751 switch (instr->Mask(
11752 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011753 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011754 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011755 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011756 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011757 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011758 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011759 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011760 case LDFF1D_z_p_bz_d_x32_scaled:
11761 case LDFF1SH_z_p_bz_d_x32_scaled:
11762 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011763 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011764 default:
11765 VIXL_UNIMPLEMENTED();
11766 break;
11767 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011768
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011769 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11770 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011771}
11772
11773void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11774 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011775 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11776 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011777 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011778 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011779 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011780 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011781 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011782 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011783 case LDFF1D_z_p_bz_d_64_scaled:
11784 case LDFF1SH_z_p_bz_d_64_scaled:
11785 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011786 break;
11787 default:
11788 VIXL_UNIMPLEMENTED();
11789 break;
11790 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011791
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011792 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011793}
11794
11795void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11796 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011797 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11798 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011799 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011800 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011801 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011802 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011803 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011804 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011805 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011806 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011807 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011808 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011809 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011810 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011811 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011812 break;
11813 default:
11814 VIXL_UNIMPLEMENTED();
11815 break;
11816 }
TatWai Chong113d9192020-05-19 01:02:36 -070011817
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011818 SVEGatherLoadScalarPlusVectorHelper(instr,
11819 kFormatVnD,
11820 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011821}
11822
11823void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11824 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011825 switch (instr->Mask(
11826 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11827 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011828 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011829 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011830 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011831 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011832 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011833 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011834 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011835 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011836 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011837 case LDFF1D_z_p_bz_d_x32_unscaled:
11838 case LDFF1SB_z_p_bz_d_x32_unscaled:
11839 case LDFF1SH_z_p_bz_d_x32_unscaled:
11840 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011841 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011842 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011843 VIXL_UNIMPLEMENTED();
11844 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011845 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011846
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011847 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11848 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011849}
11850
11851void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11852 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011853 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11854 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011855 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011856 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011857 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011858 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011859 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011860 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011861 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011862 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011863 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011864 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011865 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011866 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011867 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011868 break;
11869 default:
11870 VIXL_UNIMPLEMENTED();
11871 break;
11872 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +000011873 bool is_signed = instr->ExtractBit(14) == 0;
11874 bool is_ff = instr->ExtractBit(13) == 1;
11875 // Note that these instructions don't use the Dtype encoding.
11876 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11877 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11878 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11879 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11880 if (is_ff) {
11881 VIXL_UNIMPLEMENTED();
11882 } else {
11883 SVEStructuredLoadHelper(kFormatVnD,
11884 ReadPRegister(instr->GetPgLow8()),
11885 instr->GetRt(),
11886 addr,
11887 is_signed);
11888 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011889}
11890
11891void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11892 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011893 switch (
11894 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011895 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011896 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011897 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011898 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011899 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011900 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011901 default:
11902 VIXL_UNIMPLEMENTED();
11903 break;
11904 }
11905}
11906
11907void Simulator::
11908 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
11909 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011910 switch (instr->Mask(
11911 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011912 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011913 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011914 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011915 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011916 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011917 break;
11918 default:
11919 VIXL_UNIMPLEMENTED();
11920 break;
11921 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011922}
11923
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011924void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
11925 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011926 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011927 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011928 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011929 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011930 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011931 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011932 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011933 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011934 VIXL_UNIMPLEMENTED();
11935 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011936 }
11937}
11938
11939void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
11940 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +000011941 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +000011942 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011943 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011944 case LDFF1B_z_p_br_u16:
11945 case LDFF1B_z_p_br_u32:
11946 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011947 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011948 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011949 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011950 case LDFF1W_z_p_br_u32:
11951 case LDFF1W_z_p_br_u64:
11952 case LDFF1D_z_p_br_u64:
11953 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011954 break;
11955 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011956 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011957 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011958 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011959 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011960 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011961 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011962 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011963 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011964 // This encoding group is complete, so no other values should be possible.
11965 VIXL_UNREACHABLE();
11966 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011967 break;
11968 }
Jacob Bramley85a9c102019-12-09 17:48:29 +000011969
11970 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11971 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11972 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11973 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11974 uint64_t offset = ReadXRegister(instr->GetRm());
11975 offset <<= msize_in_bytes_log2;
11976 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11977 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11978 SVEFaultTolerantLoadHelper(vform,
11979 ReadPRegister(instr->GetPgLow8()),
11980 instr->GetRt(),
11981 addr,
11982 kSVEFirstFaultLoad,
11983 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011984}
11985
11986void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
11987 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011988 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011989 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011990 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011991 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011992 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011993 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011994 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011995 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011996 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011997 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000011998 case LDNF1W_z_p_bi_u32:
11999 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012000 break;
12001 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012002 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012003 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012004 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012005 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012006 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012007 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012008 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012009 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012010 VIXL_UNIMPLEMENTED();
12011 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012012 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012013 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12014 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12015 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12016 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12017 int vl = GetVectorLengthInBytes();
12018 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12019 uint64_t offset =
12020 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12021 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12022 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12023 SVEFaultTolerantLoadHelper(vform,
12024 ReadPRegister(instr->GetPgLow8()),
12025 instr->GetRt(),
12026 addr,
12027 kSVENonFaultLoad,
12028 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012029}
12030
12031void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12032 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012033 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12034 VectorFormat vform = kFormatUndefined;
12035
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012036 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12037 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012038 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012039 break;
12040 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012041 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012042 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012043 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012044 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012045 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012046 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012047 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012048 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012049 default:
12050 VIXL_UNIMPLEMENTED();
12051 break;
12052 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012053 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12054 int vl = GetVectorLengthInBytes();
12055 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12056 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12057 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12058 SVEStructuredLoadHelper(vform,
12059 pg,
12060 instr->GetRt(),
12061 addr,
12062 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012063}
12064
12065void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12066 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012067 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12068 VectorFormat vform = kFormatUndefined;
12069
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012070 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12071 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012072 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012073 break;
12074 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012075 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012076 break;
12077 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012078 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012079 break;
12080 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012081 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012082 break;
12083 default:
12084 VIXL_UNIMPLEMENTED();
12085 break;
12086 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012087 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12088 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12089 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12090 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12091 SVEStructuredLoadHelper(vform,
12092 pg,
12093 instr->GetRt(),
12094 addr,
12095 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012096}
12097
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012098void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
12099 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012100 SimVRegister& zt = ReadVRegister(instr->GetRt());
12101 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12102
12103 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12104 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
12105
12106 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012107 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
12108 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012109 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012110 break;
12111 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012112 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012113 break;
12114 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012115 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012116 break;
12117 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012118 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012119 break;
12120 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012121 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012122 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012123 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012124 ld1(kFormat16B, zt, addr + offset);
12125 mov_zeroing(vform, zt, pg, zt);
12126 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012127}
12128
12129void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
12130 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012131 SimVRegister& zt = ReadVRegister(instr->GetRt());
12132 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12133
12134 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12135 uint64_t offset = ReadXRegister(instr->GetRm());
12136
12137 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012138 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
12139 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012140 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012141 break;
12142 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012143 vform = kFormatVnD;
12144 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012145 break;
12146 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012147 vform = kFormatVnH;
12148 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012149 break;
12150 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012151 vform = kFormatVnS;
12152 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012153 break;
12154 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012155 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012156 break;
12157 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012158 ld1(kFormat16B, zt, addr + offset);
12159 mov_zeroing(vform, zt, pg, zt);
12160 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012161}
12162
12163void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12164 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012165 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12166 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012167 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012168 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012169 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012170 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012171 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012172 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012173 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012174 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012175 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012176 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012177 case LD4W_z_p_bi_contiguous: {
12178 int vl = GetVectorLengthInBytes();
12179 int msz = instr->ExtractBits(24, 23);
12180 int reg_count = instr->ExtractBits(22, 21) + 1;
12181 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12182 LogicSVEAddressVector addr(
12183 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12184 addr.SetMsizeInBytesLog2(msz);
12185 addr.SetRegCount(reg_count);
12186 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12187 ReadPRegister(instr->GetPgLow8()),
12188 instr->GetRt(),
12189 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012190 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012191 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012192 default:
12193 VIXL_UNIMPLEMENTED();
12194 break;
12195 }
12196}
12197
12198void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12199 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012200 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12201 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012202 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012203 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012204 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012205 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012206 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012207 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012208 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012209 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012210 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012211 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000012212 case LD4W_z_p_br_contiguous: {
12213 int msz = instr->ExtractBits(24, 23);
12214 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12215 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12216 LogicSVEAddressVector addr(
12217 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12218 addr.SetMsizeInBytesLog2(msz);
12219 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12220 SVEStructuredLoadHelper(vform,
12221 ReadPRegister(instr->GetPgLow8()),
12222 instr->GetRt(),
12223 addr,
12224 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012225 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000012226 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012227 default:
12228 VIXL_UNIMPLEMENTED();
12229 break;
12230 }
12231}
12232
12233void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12234 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012235 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12236 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012237 case ST1W_z_p_bz_s_x32_scaled: {
12238 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12239 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12240 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12241 uint64_t base = ReadXRegister(instr->GetRn());
12242 SVEOffsetModifier mod =
12243 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12244 LogicSVEAddressVector addr(base,
12245 &ReadVRegister(instr->GetRm()),
12246 kFormatVnS,
12247 mod,
12248 scale);
12249 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12250 SVEStructuredStoreHelper(kFormatVnS,
12251 ReadPRegister(instr->GetPgLow8()),
12252 instr->GetRt(),
12253 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012254 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012255 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012256 default:
12257 VIXL_UNIMPLEMENTED();
12258 break;
12259 }
12260}
12261
12262void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12263 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012264 switch (
12265 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12266 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012267 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012268 case ST1W_z_p_bz_s_x32_unscaled: {
12269 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12270 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12271 uint64_t base = ReadXRegister(instr->GetRn());
12272 SVEOffsetModifier mod =
12273 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12274 LogicSVEAddressVector addr(base,
12275 &ReadVRegister(instr->GetRm()),
12276 kFormatVnS,
12277 mod);
12278 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12279 SVEStructuredStoreHelper(kFormatVnS,
12280 ReadPRegister(instr->GetPgLow8()),
12281 instr->GetRt(),
12282 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012283 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012284 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012285 default:
12286 VIXL_UNIMPLEMENTED();
12287 break;
12288 }
12289}
12290
12291void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12292 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012293 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012294 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12295 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012296 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012297 break;
12298 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012299 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012300 break;
12301 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012302 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012303 break;
12304 default:
12305 VIXL_UNIMPLEMENTED();
12306 break;
12307 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012308 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12309 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12310 addr.SetMsizeInBytesLog2(msz);
12311 SVEStructuredStoreHelper(kFormatVnS,
12312 ReadPRegister(instr->GetPgLow8()),
12313 instr->GetRt(),
12314 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012315}
12316
12317void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12318 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012319 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12320 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012321 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012322 case ST1W_z_p_bz_d_64_scaled: {
12323 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12324 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12325 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12326 uint64_t base = ReadXRegister(instr->GetRn());
12327 LogicSVEAddressVector addr(base,
12328 &ReadVRegister(instr->GetRm()),
12329 kFormatVnD,
12330 SVE_LSL,
12331 scale);
12332 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12333 SVEStructuredStoreHelper(kFormatVnD,
12334 ReadPRegister(instr->GetPgLow8()),
12335 instr->GetRt(),
12336 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012337 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012338 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012339 default:
12340 VIXL_UNIMPLEMENTED();
12341 break;
12342 }
12343}
12344
12345void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12346 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012347 switch (
12348 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12349 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012350 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012351 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012352 case ST1W_z_p_bz_d_64_unscaled: {
12353 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12354 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012355 uint64_t base = ReadXRegister(instr->GetRn());
12356 LogicSVEAddressVector addr(base,
12357 &ReadVRegister(instr->GetRm()),
12358 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070012359 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012360 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12361 SVEStructuredStoreHelper(kFormatVnD,
12362 ReadPRegister(instr->GetPgLow8()),
12363 instr->GetRt(),
12364 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012365 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012366 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012367 default:
12368 VIXL_UNIMPLEMENTED();
12369 break;
12370 }
12371}
12372
12373void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12374 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012375 switch (instr->Mask(
12376 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12377 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012378 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012379 case ST1W_z_p_bz_d_x32_scaled: {
12380 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12381 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12382 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12383 uint64_t base = ReadXRegister(instr->GetRn());
12384 SVEOffsetModifier mod =
12385 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12386 LogicSVEAddressVector addr(base,
12387 &ReadVRegister(instr->GetRm()),
12388 kFormatVnD,
12389 mod,
12390 scale);
12391 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12392 SVEStructuredStoreHelper(kFormatVnD,
12393 ReadPRegister(instr->GetPgLow8()),
12394 instr->GetRt(),
12395 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012396 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012397 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012398 default:
12399 VIXL_UNIMPLEMENTED();
12400 break;
12401 }
12402}
12403
12404void Simulator::
12405 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12406 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012407 switch (instr->Mask(
12408 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12409 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012410 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012411 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012412 case ST1W_z_p_bz_d_x32_unscaled: {
12413 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12414 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12415 uint64_t base = ReadXRegister(instr->GetRn());
12416 SVEOffsetModifier mod =
12417 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12418 LogicSVEAddressVector addr(base,
12419 &ReadVRegister(instr->GetRm()),
12420 kFormatVnD,
12421 mod);
12422 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12423 SVEStructuredStoreHelper(kFormatVnD,
12424 ReadPRegister(instr->GetPgLow8()),
12425 instr->GetRt(),
12426 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012427 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012428 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012429 default:
12430 VIXL_UNIMPLEMENTED();
12431 break;
12432 }
12433}
12434
12435void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12436 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012437 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012438 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12439 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012440 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012441 break;
12442 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012443 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012444 break;
12445 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012446 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012447 break;
12448 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012449 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012450 break;
12451 default:
12452 VIXL_UNIMPLEMENTED();
12453 break;
12454 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012455 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12456 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12457 addr.SetMsizeInBytesLog2(msz);
12458 SVEStructuredStoreHelper(kFormatVnD,
12459 ReadPRegister(instr->GetPgLow8()),
12460 instr->GetRt(),
12461 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012462}
12463
12464void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12465 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012466 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12467 VectorFormat vform = kFormatUndefined;
12468
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012469 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12470 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012471 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012472 break;
12473 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012474 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012475 break;
12476 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012477 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012478 break;
12479 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012480 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012481 break;
12482 default:
12483 VIXL_UNIMPLEMENTED();
12484 break;
12485 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012486 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12487 int vl = GetVectorLengthInBytes();
12488 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12489 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12490 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12491 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012492}
12493
12494void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12495 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012496 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12497 VectorFormat vform = kFormatUndefined;
12498
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012499 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12500 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012501 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012502 break;
12503 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012504 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012505 break;
12506 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012507 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012508 break;
12509 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012510 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012511 break;
12512 default:
12513 VIXL_UNIMPLEMENTED();
12514 break;
12515 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012516 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12517 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12518 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12519 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12520 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012521}
12522
12523void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12524 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012525 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12526 case ST1B_z_p_bi:
12527 case ST1D_z_p_bi:
12528 case ST1H_z_p_bi:
12529 case ST1W_z_p_bi: {
12530 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012531 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12532 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12533 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12534 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12535 uint64_t offset =
12536 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012537 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012538 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012539 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012540 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12541 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012542 ReadPRegister(instr->GetPgLow8()),
12543 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012544 addr);
12545 break;
12546 }
12547 default:
12548 VIXL_UNIMPLEMENTED();
12549 break;
12550 }
12551}
12552
12553void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12554 const Instruction* instr) {
12555 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12556 case ST1B_z_p_br:
12557 case ST1D_z_p_br:
12558 case ST1H_z_p_br:
12559 case ST1W_z_p_br: {
12560 uint64_t offset = ReadXRegister(instr->GetRm());
12561 offset <<= instr->ExtractBits(24, 23);
12562 VectorFormat vform =
12563 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12564 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012565 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12566 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012567 ReadPRegister(instr->GetPgLow8()),
12568 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012569 addr);
12570 break;
12571 }
12572 default:
12573 VIXL_UNIMPLEMENTED();
12574 break;
12575 }
12576}
12577
12578void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12579 const Instruction* instr) {
12580 VectorFormat vform = instr->GetSVEVectorFormat();
12581 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12582 SimVRegister z_result;
12583
12584 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12585 case CPY_z_p_v:
12586 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12587 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12588 break;
12589 default:
12590 VIXL_UNIMPLEMENTED();
12591 break;
12592 }
12593}
12594
12595void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12596 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012597 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12598 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012599 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012600 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012601 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012602 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012603 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012604 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012605 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012606 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012607 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012608 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012609 case ST4W_z_p_bi_contiguous: {
12610 int vl = GetVectorLengthInBytes();
12611 int msz = instr->ExtractBits(24, 23);
12612 int reg_count = instr->ExtractBits(22, 21) + 1;
12613 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12614 LogicSVEAddressVector addr(
12615 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12616 addr.SetMsizeInBytesLog2(msz);
12617 addr.SetRegCount(reg_count);
12618 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12619 ReadPRegister(instr->GetPgLow8()),
12620 instr->GetRt(),
12621 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012622 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012623 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012624 default:
12625 VIXL_UNIMPLEMENTED();
12626 break;
12627 }
12628}
12629
12630void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12631 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012632 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12633 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012634 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012635 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012636 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012637 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012638 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012639 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012640 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012641 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012642 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012643 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012644 case ST4W_z_p_br_contiguous: {
12645 int msz = instr->ExtractBits(24, 23);
12646 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12647 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12648 LogicSVEAddressVector addr(
12649 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12650 addr.SetMsizeInBytesLog2(msz);
12651 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12652 SVEStructuredStoreHelper(vform,
12653 ReadPRegister(instr->GetPgLow8()),
12654 instr->GetRt(),
12655 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012656 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012657 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012658 default:
12659 VIXL_UNIMPLEMENTED();
12660 break;
12661 }
12662}
12663
12664void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12665 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12666 case STR_p_bi: {
12667 SimPRegister& pt = ReadPRegister(instr->GetPt());
12668 int pl = GetPredicateLengthInBytes();
12669 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12670 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12671 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12672 for (int i = 0; i < pl; i++) {
12673 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
12674 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012675 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012676 break;
12677 }
12678 default:
12679 VIXL_UNIMPLEMENTED();
12680 break;
12681 }
12682}
12683
12684void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12685 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12686 case STR_z_bi: {
12687 SimVRegister& zt = ReadVRegister(instr->GetRt());
12688 int vl = GetVectorLengthInBytes();
12689 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12690 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12691 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12692 for (int i = 0; i < vl; i++) {
12693 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
12694 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012695 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012696 break;
12697 }
12698 default:
12699 VIXL_UNIMPLEMENTED();
12700 break;
12701 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012702}
12703
12704void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012705 VectorFormat vform = instr->GetSVEVectorFormat();
12706 SimVRegister& zda = ReadVRegister(instr->GetRd());
12707 SimVRegister& zn = ReadVRegister(instr->GetRn());
12708
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012709 switch (instr->Mask(SVEMulIndexMask)) {
12710 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012711 sdot(vform,
12712 zda,
12713 zn,
12714 ReadVRegister(instr->ExtractBits(19, 16)),
12715 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012716 break;
12717 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012718 sdot(vform,
12719 zda,
12720 zn,
12721 ReadVRegister(instr->ExtractBits(18, 16)),
12722 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012723 break;
12724 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012725 udot(vform,
12726 zda,
12727 zn,
12728 ReadVRegister(instr->ExtractBits(19, 16)),
12729 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012730 break;
12731 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012732 udot(vform,
12733 zda,
12734 zn,
12735 ReadVRegister(instr->ExtractBits(18, 16)),
12736 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012737 break;
12738 default:
12739 VIXL_UNIMPLEMENTED();
12740 break;
12741 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012742}
12743
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012744void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012745 SimPRegister& pd = ReadPRegister(instr->GetPd());
12746 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12747 SimPRegister& pn = ReadPRegister(instr->GetPn());
12748 SimPRegister result;
12749
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012750 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012751 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012752 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012753 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012754 break;
12755 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012756 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012757 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012758 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012759 default:
12760 VIXL_UNIMPLEMENTED();
12761 break;
12762 }
TatWai Chong5d872292020-01-02 15:39:51 -080012763
12764 if (instr->ExtractBit(4) == 1) {
12765 mov_merging(pd, pg, result);
12766 } else {
12767 mov_zeroing(pd, pg, result);
12768 }
12769
12770 // Set flag if needed.
12771 if (instr->ExtractBit(22) == 1) {
12772 PredTest(kFormatVnB, pg, pd);
12773 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012774}
12775
12776void Simulator::VisitSVEPropagateBreakToNextPartition(
12777 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012778 SimPRegister& pdm = ReadPRegister(instr->GetPd());
12779 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12780 SimPRegister& pn = ReadPRegister(instr->GetPn());
12781
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012782 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012783 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012784 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080012785 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012786 break;
12787 default:
12788 VIXL_UNIMPLEMENTED();
12789 break;
12790 }
TatWai Chong5d872292020-01-02 15:39:51 -080012791
12792 // Set flag if needed.
12793 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010012794 // Note that this ignores `pg`.
12795 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080012796 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012797}
12798
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012799void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012800 SimPRegister& pd = ReadPRegister(instr->GetPd());
12801 SimPRegister& pn = ReadPRegister(instr->GetPn());
12802
12803 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12804 SimVRegister zero;
12805 dup_immediate(kFormatVnB, zero, 0);
12806
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012807 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012808 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012809 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012810 break;
12811 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012812 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012813 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012814 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012815 VIXL_UNIMPLEMENTED();
12816 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012817 }
TatWai Chong47c26842020-02-10 01:51:32 -080012818 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012819}
12820
12821void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012822 VectorFormat vform = instr->GetSVEVectorFormat();
12823 SimPRegister& pd = ReadPRegister(instr->GetPd());
12824 SimPRegister& pn = ReadPRegister(instr->GetPn());
12825 SimPRegister& pm = ReadPRegister(instr->GetPm());
12826
12827 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12828 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12829
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012830 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012831 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012832 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012833 break;
12834 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012835 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012836 break;
12837 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012838 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012839 break;
12840 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012841 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012842 break;
12843 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012844 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012845 break;
12846 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012847 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012848 break;
12849 default:
12850 VIXL_UNIMPLEMENTED();
12851 break;
12852 }
TatWai Chong47c26842020-02-10 01:51:32 -080012853 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012854}
12855
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012856void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012857 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012858 case REV_p_p: {
12859 VectorFormat vform = instr->GetSVEVectorFormat();
12860 SimPRegister& pn = ReadPRegister(instr->GetPn());
12861 SimPRegister& pd = ReadPRegister(instr->GetPd());
12862 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12863 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080012864 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012865 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012866 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012867 default:
12868 VIXL_UNIMPLEMENTED();
12869 break;
12870 }
12871}
12872
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012873void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000012874 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12875 // Second source register "Zm" is encoded where "Zn" would usually be.
12876 SimVRegister& zm = ReadVRegister(instr->GetRn());
12877
12878 const int imm8h_mask = 0x001F0000;
12879 const int imm8l_mask = 0x00001C00;
12880 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
12881 int vl = GetVectorLengthInBytes();
12882 index = (index >= vl) ? 0 : index;
12883
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012884 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
12885 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000012886 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012887 break;
12888 default:
12889 VIXL_UNIMPLEMENTED();
12890 break;
12891 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012892}
12893
12894void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000012895 VectorFormat vform = instr->GetSVEVectorFormat();
12896 SimVRegister& zd = ReadVRegister(instr->GetRd());
12897 SimVRegister& zn = ReadVRegister(instr->GetRn());
12898 SimVRegister& zm = ReadVRegister(instr->GetRm());
12899
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012900 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
12901 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012902 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012903 break;
12904 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012905 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012906 break;
12907 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012908 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012909 break;
12910 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012911 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012912 break;
12913 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012914 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012915 break;
12916 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012917 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012918 break;
12919 default:
12920 VIXL_UNIMPLEMENTED();
12921 break;
12922 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012923}
12924
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012925void Simulator::VisitSVEConditionallyBroadcastElementToVector(
12926 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012927 VectorFormat vform = instr->GetSVEVectorFormat();
12928 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12929 SimVRegister& zm = ReadVRegister(instr->GetRn());
12930 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12931
12932 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012933 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012934 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012935 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012936 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012937 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012938 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012939 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012940 default:
12941 VIXL_UNIMPLEMENTED();
12942 break;
12943 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012944
12945 if (active_offset >= 0) {
12946 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12947 if (value.first) {
12948 dup_immediate(vform, zdn, value.second);
12949 } else {
12950 // Trigger a line of trace for the operation, even though it doesn't
12951 // change the register value.
12952 mov(vform, zdn, zdn);
12953 }
12954 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012955}
12956
12957void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
12958 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012959 VectorFormat vform = instr->GetSVEVectorFormat();
12960 SimVRegister& vdn = ReadVRegister(instr->GetRd());
12961 SimVRegister& zm = ReadVRegister(instr->GetRn());
12962 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12963
12964 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012965 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
12966 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012967 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012968 break;
12969 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012970 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012971 break;
12972 default:
12973 VIXL_UNIMPLEMENTED();
12974 break;
12975 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012976
12977 if (active_offset >= 0) {
12978 LogicVRegister dst(vdn);
12979 uint64_t src1_value = dst.Uint(vform, 0);
12980 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
12981 dup_immediate(vform, vdn, 0);
12982 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
12983 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012984}
12985
12986void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
12987 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012988 VectorFormat vform = instr->GetSVEVectorFormat();
12989 SimVRegister& zm = ReadVRegister(instr->GetRn());
12990 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12991
12992 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012993 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
12994 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012995 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012996 break;
12997 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000012998 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012999 break;
13000 default:
13001 VIXL_UNIMPLEMENTED();
13002 break;
13003 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013004
13005 if (active_offset >= 0) {
13006 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13007 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13008 GetUintMask(LaneSizeInBitsFromFormat(vform));
13009 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13010 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013011}
13012
13013void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13014 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013015 VectorFormat vform = instr->GetSVEVectorFormat();
13016 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13017 SimVRegister& zm = ReadVRegister(instr->GetRn());
13018 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13019
13020 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013021 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13022 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013023 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013024 break;
13025 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013026 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013027 break;
13028 default:
13029 VIXL_UNIMPLEMENTED();
13030 break;
13031 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013032
13033 if (active_offset >= 0) {
13034 LogicVRegister dst(vdn);
13035 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13036 dup_immediate(vform, vdn, 0);
13037 dst.SetUint(vform, 0, value.second);
13038 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013039}
13040
13041void Simulator::VisitSVEExtractElementToGeneralRegister(
13042 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013043 VectorFormat vform = instr->GetSVEVectorFormat();
13044 SimVRegister& zm = ReadVRegister(instr->GetRn());
13045 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13046
13047 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013048 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13049 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013050 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013051 break;
13052 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013053 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013054 break;
13055 default:
13056 VIXL_UNIMPLEMENTED();
13057 break;
13058 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013059
13060 if (active_offset >= 0) {
13061 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13062 WriteXRegister(instr->GetRd(), value.second);
13063 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013064}
13065
13066void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013067 VectorFormat vform = instr->GetSVEVectorFormat();
13068 SimVRegister& zd = ReadVRegister(instr->GetRd());
13069 SimVRegister& zn = ReadVRegister(instr->GetRn());
13070 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13071
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013072 switch (instr->Mask(SVECompressActiveElementsMask)) {
13073 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013074 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013075 break;
13076 default:
13077 VIXL_UNIMPLEMENTED();
13078 break;
13079 }
13080}
13081
13082void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13083 const Instruction* instr) {
13084 VectorFormat vform = instr->GetSVEVectorFormat();
13085 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13086 SimVRegister z_result;
13087
13088 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013089 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010013090 dup_immediate(vform,
13091 z_result,
13092 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13093 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013094 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013095 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013096 VIXL_UNIMPLEMENTED();
13097 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013098 }
13099}
13100
13101void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013102 VectorFormat vform = instr->GetSVEVectorFormat();
13103 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13104 SimVRegister& zd = ReadVRegister(instr->GetRd());
13105
13106 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013107 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013108 case CPY_z_p_i: {
13109 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
13110 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13111 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013112 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013113 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013114 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013115 VIXL_UNIMPLEMENTED();
13116 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013117 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013118
13119 if (instr->ExtractBit(14) != 0) {
13120 mov_merging(vform, zd, pg, result);
13121 } else {
13122 mov_zeroing(vform, zd, pg, result);
13123 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013124}
13125
13126void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000013127 SimVRegister& zd = ReadVRegister(instr->GetRd());
13128 SimVRegister& zn = ReadVRegister(instr->GetRn());
13129 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13130 SimVRegister result;
13131
13132 // In NEON, the chunk size in which elements are REVersed is in the
13133 // instruction mnemonic, and the element size attached to the register.
13134 // SVE reverses the semantics; the mapping to logic functions below is to
13135 // account for this.
13136 VectorFormat chunk_form = instr->GetSVEVectorFormat();
13137 VectorFormat element_form = kFormatUndefined;
13138
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013139 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013140 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013141 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013142 break;
13143 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013144 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13145 (chunk_form == kFormatVnD));
13146 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013147 break;
13148 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013149 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13150 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013151 break;
13152 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013153 VIXL_ASSERT(chunk_form == kFormatVnD);
13154 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013155 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013156 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013157 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013158 break;
13159 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000013160
13161 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13162 VIXL_ASSERT(element_form != kFormatUndefined);
13163 switch (chunk_form) {
13164 case kFormatVnH:
13165 rev16(element_form, result, zn);
13166 break;
13167 case kFormatVnS:
13168 rev32(element_form, result, zn);
13169 break;
13170 case kFormatVnD:
13171 rev64(element_form, result, zn);
13172 break;
13173 default:
13174 VIXL_UNIMPLEMENTED();
13175 }
13176 }
13177
13178 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013179}
13180
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013181void Simulator::VisitSVEVectorSplice(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013182 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013183 SimVRegister& zd = ReadVRegister(instr->GetRd());
13184 SimVRegister& zn = ReadVRegister(instr->GetRn());
13185 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
Martyn Capewellf804b602020-02-24 18:57:18 +000013186 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13187
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013188 switch (form_hash_) {
13189 case Hash("splice_z_p_zz_des"):
13190 splice(vform, zd, pg, zd, zn);
13191 break;
13192 case Hash("splice_z_p_zz_con"):
13193 splice(vform, zd, pg, zn, zn2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013194 break;
13195 default:
13196 VIXL_UNIMPLEMENTED();
13197 break;
13198 }
13199}
TatWai Chong4f28df72019-08-14 17:50:30 -070013200
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013201void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13202 SimVRegister& zd = ReadVRegister(instr->GetRd());
13203 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13204 case DUP_z_r:
13205 dup_immediate(instr->GetSVEVectorFormat(),
13206 zd,
13207 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13208 break;
13209 default:
13210 VIXL_UNIMPLEMENTED();
13211 break;
13212 }
13213}
13214
13215void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13216 SimVRegister& zd = ReadVRegister(instr->GetRd());
13217 VectorFormat vform = instr->GetSVEVectorFormat();
13218 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13219 case INSR_z_v:
13220 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13221 break;
13222 default:
13223 VIXL_UNIMPLEMENTED();
13224 break;
13225 }
13226}
13227
13228void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13229 SimVRegister& zd = ReadVRegister(instr->GetRd());
13230 VectorFormat vform = instr->GetSVEVectorFormat();
13231 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13232 case INSR_z_r:
13233 insr(vform, zd, ReadXRegister(instr->GetRn()));
13234 break;
13235 default:
13236 VIXL_UNIMPLEMENTED();
13237 break;
13238 }
13239}
13240
13241void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13242 SimVRegister& zd = ReadVRegister(instr->GetRd());
13243 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070013244 case DUP_z_zi: {
13245 std::pair<int, int> index_and_lane_size =
13246 instr->GetSVEPermuteIndexAndLaneSizeLog2();
13247 int index = index_and_lane_size.first;
13248 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13249 VectorFormat vform =
13250 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13251 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13252 // Out of bounds, set the destination register to zero.
13253 dup_immediate(kFormatVnD, zd, 0);
13254 } else {
13255 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13256 }
13257 return;
13258 }
TatWai Chong4f28df72019-08-14 17:50:30 -070013259 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013260 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070013261 break;
13262 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013263}
TatWai Chong4f28df72019-08-14 17:50:30 -070013264
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013265void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13266 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070013267 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013268 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013269 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013270 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013271 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013272 default:
13273 VIXL_UNIMPLEMENTED();
13274 break;
13275 }
13276}
13277
13278void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13279 SimVRegister& zd = ReadVRegister(instr->GetRd());
13280 VectorFormat vform = instr->GetSVEVectorFormat();
13281 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013282 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013283 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013284 break;
13285 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013286 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013287 break;
13288 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013289 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013290 break;
13291 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013292 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13293 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013294 default:
13295 VIXL_UNIMPLEMENTED();
13296 break;
13297 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013298}
13299
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013300void Simulator::VisitSVETableLookup(const Instruction* instr) {
Martyn Capewell99c60492020-10-30 08:14:39 +000013301 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013302 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell99c60492020-10-30 08:14:39 +000013303 SimVRegister& zn = ReadVRegister(instr->GetRn());
13304 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13305 SimVRegister& zm = ReadVRegister(instr->GetRm());
13306
13307 switch (form_hash_) {
13308 case Hash("tbl_z_zz_1"):
13309 tbl(vform, zd, zn, zm);
13310 break;
13311 case Hash("tbl_z_zz_2"):
13312 tbl(vform, zd, zn, zn2, zm);
13313 break;
13314 case Hash("tbx_z_zz"):
13315 tbx(vform, zd, zn, zm);
13316 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013317 default:
Martyn Capewell99c60492020-10-30 08:14:39 +000013318 VIXL_UNIMPLEMENTED();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013319 break;
13320 }
13321}
13322
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013323void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013324 VectorFormat vform = instr->GetSVEVectorFormat();
13325 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13326 SimPRegister& pn = ReadPRegister(instr->GetPn());
13327
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013328 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013329 case CNTP_r_p_p: {
13330 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013331 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013332 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013333 default:
13334 VIXL_UNIMPLEMENTED();
13335 break;
13336 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013337}
13338
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013339void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13340 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080013341 SimPRegister& pd = ReadPRegister(instr->GetPd());
13342 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13343 SimPRegister& pn = ReadPRegister(instr->GetPn());
13344 SimPRegister& pm = ReadPRegister(instr->GetPm());
13345 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070013346 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013347 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013348 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013349 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013350 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013351 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013352 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013353 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013354 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013355 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013356 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013357 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013358 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013359 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013360 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070013361 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080013362 result,
13363 pn,
13364 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013365 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080013366 case SEL_p_p_pp:
13367 sel(pd, pg, pn, pm);
13368 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013369 default:
13370 VIXL_UNIMPLEMENTED();
13371 break;
13372 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013373
13374 mov_zeroing(pd, pg, result);
13375 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13376 PredTest(kFormatVnB, pg, pd);
13377 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013378}
13379
Jacob Bramley0ce75842019-07-17 18:12:50 +010013380void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013381 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13382 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13383 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013384 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010013385 pfirst(pdn, pg, pdn);
13386 // TODO: Is this broken when pg == pdn?
13387 PredTest(kFormatVnB, pg, pdn);
13388 break;
13389 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013390 VIXL_UNIMPLEMENTED();
13391 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013392 }
13393}
13394
13395void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013396 // This group only contains PTRUE{S}, and there are no unallocated encodings.
13397 VIXL_STATIC_ASSERT(
13398 SVEPredicateInitializeMask ==
13399 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13400 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13401 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13402
13403 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13404 VectorFormat vform = instr->GetSVEVectorFormat();
13405
13406 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13407 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13408}
13409
13410void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013411 // This group only contains PNEXT, and there are no unallocated encodings.
13412 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13413 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13414
13415 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13416 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13417 VectorFormat vform = instr->GetSVEVectorFormat();
13418
13419 pnext(vform, pdn, pg, pdn);
13420 // TODO: Is this broken when pg == pdn?
13421 PredTest(vform, pg, pdn);
13422}
13423
13424void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13425 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080013426 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13427 LogicPRegister pg(ReadPRegister(instr->GetPn()));
13428 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013429 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13430 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013431 // Do nothing.
13432 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013433 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013434 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013435 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013436 default:
13437 VIXL_UNIMPLEMENTED();
13438 break;
13439 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013440
13441 LogicPRegister ffr(ReadFFR());
13442 mov_zeroing(pd, pg, ffr);
13443
13444 if (flags == SetFlags) {
13445 PredTest(kFormatVnB, pg, pd);
13446 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010013447}
13448
13449void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13450 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013451 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13452 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010013453 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013454 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080013455 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013456 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013457 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013458 VIXL_UNIMPLEMENTED();
13459 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013460 }
13461}
13462
13463void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013464 switch (instr->Mask(SVEPredicateTestMask)) {
13465 case PTEST_p_p:
13466 PredTest(kFormatVnB,
13467 ReadPRegister(instr->ExtractBits(13, 10)),
13468 ReadPRegister(instr->GetPn()));
13469 break;
13470 default:
13471 VIXL_UNIMPLEMENTED();
13472 break;
13473 }
13474}
13475
13476void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013477 switch (instr->Mask(SVEPredicateZeroMask)) {
13478 case PFALSE_p:
13479 pfalse(ReadPRegister(instr->GetPd()));
13480 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013481 default:
13482 VIXL_UNIMPLEMENTED();
13483 break;
13484 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013485}
13486
13487void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080013488 SimPRegister& pd = ReadPRegister(instr->GetPd());
13489 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13490 SimPRegister& pn = ReadPRegister(instr->GetPn());
13491 SimPRegister& pm = ReadPRegister(instr->GetPm());
13492
13493 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013494 switch (instr->Mask(SVEPropagateBreakMask)) {
13495 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013496 set_flags = true;
13497 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013498 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013499 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013500 break;
13501 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013502 set_flags = true;
13503 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013504 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013505 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013506 break;
13507 default:
13508 VIXL_UNIMPLEMENTED();
13509 break;
13510 }
TatWai Chong38303d92019-12-02 15:49:29 -080013511
13512 if (set_flags) {
13513 PredTest(kFormatVnB, pg, pd);
13514 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013515}
13516
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013517void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13518 uint64_t length = 0;
13519 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13520 case ADDPL_r_ri:
13521 length = GetPredicateLengthInBytes();
13522 break;
13523 case ADDVL_r_ri:
13524 length = GetVectorLengthInBytes();
13525 break;
13526 default:
13527 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013528 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013529 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013530 WriteXRegister(instr->GetRd(),
13531 base + (length * instr->GetImmSVEVLScale()),
13532 LogRegWrites,
13533 Reg31IsStackPointer);
13534}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013535
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013536void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13537 int64_t scale = instr->GetImmSVEVLScale();
13538
13539 switch (instr->Mask(SVEStackFrameSizeMask)) {
13540 case RDVL_r_i:
13541 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13542 break;
13543 default:
13544 VIXL_UNIMPLEMENTED();
13545 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013546}
13547
13548void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013549 // The only instruction in this group is `sel`, and there are no unused
13550 // encodings.
13551 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13552
13553 VectorFormat vform = instr->GetSVEVectorFormat();
13554 SimVRegister& zd = ReadVRegister(instr->GetRd());
13555 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13556 SimVRegister& zn = ReadVRegister(instr->GetRn());
13557 SimVRegister& zm = ReadVRegister(instr->GetRm());
13558
13559 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013560}
13561
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013562void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013563 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013564 case SETFFR_f: {
13565 LogicPRegister ffr(ReadFFR());
13566 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013567 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013568 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013569 default:
13570 VIXL_UNIMPLEMENTED();
13571 break;
13572 }
13573}
13574
13575void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013576 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013577 case WRFFR_f_p: {
13578 SimPRegister pn(ReadPRegister(instr->GetPn()));
13579 bool last_active = true;
13580 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13581 bool active = pn.GetBit(i);
13582 if (active && !last_active) {
13583 // `pn` is non-monotonic. This is UNPREDICTABLE.
13584 VIXL_ABORT();
13585 }
13586 last_active = active;
13587 }
13588 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013589 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013590 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013591 default:
13592 VIXL_UNIMPLEMENTED();
13593 break;
13594 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013595}
Alexandre Ramesd3832962016-07-04 15:03:43 +010013596
TatWai Chong6205eb42019-09-24 10:07:20 +010013597void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013598 bool is_signed;
13599 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13600 case LD1B_z_p_bi_u8:
13601 case LD1B_z_p_bi_u16:
13602 case LD1B_z_p_bi_u32:
13603 case LD1B_z_p_bi_u64:
13604 case LD1H_z_p_bi_u16:
13605 case LD1H_z_p_bi_u32:
13606 case LD1H_z_p_bi_u64:
13607 case LD1W_z_p_bi_u32:
13608 case LD1W_z_p_bi_u64:
13609 case LD1D_z_p_bi_u64:
13610 is_signed = false;
13611 break;
13612 case LD1SB_z_p_bi_s16:
13613 case LD1SB_z_p_bi_s32:
13614 case LD1SB_z_p_bi_s64:
13615 case LD1SH_z_p_bi_s32:
13616 case LD1SH_z_p_bi_s64:
13617 case LD1SW_z_p_bi_s64:
13618 is_signed = true;
13619 break;
13620 default:
13621 // This encoding group is complete, so no other values should be possible.
13622 VIXL_UNREACHABLE();
13623 is_signed = false;
13624 break;
13625 }
13626
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013627 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010013628 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13629 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013630 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13631 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13632 uint64_t offset =
13633 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013634 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013635 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013636 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13637 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013638 ReadPRegister(instr->GetPgLow8()),
13639 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013640 addr,
13641 is_signed);
13642}
13643
13644void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13645 const Instruction* instr) {
13646 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010013647 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13648 case LD1B_z_p_br_u8:
13649 case LD1B_z_p_br_u16:
13650 case LD1B_z_p_br_u32:
13651 case LD1B_z_p_br_u64:
13652 case LD1H_z_p_br_u16:
13653 case LD1H_z_p_br_u32:
13654 case LD1H_z_p_br_u64:
13655 case LD1W_z_p_br_u32:
13656 case LD1W_z_p_br_u64:
13657 case LD1D_z_p_br_u64:
13658 is_signed = false;
13659 break;
13660 case LD1SB_z_p_br_s16:
13661 case LD1SB_z_p_br_s32:
13662 case LD1SB_z_p_br_s64:
13663 case LD1SH_z_p_br_s32:
13664 case LD1SH_z_p_br_s64:
13665 case LD1SW_z_p_br_s64:
13666 is_signed = true;
13667 break;
13668 default:
13669 // This encoding group is complete, so no other values should be possible.
13670 VIXL_UNREACHABLE();
13671 is_signed = false;
13672 break;
13673 }
13674
13675 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13676 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13677 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13678 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13679 uint64_t offset = ReadXRegister(instr->GetRm());
13680 offset <<= msize_in_bytes_log2;
13681 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013682 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13683 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013684 ReadPRegister(instr->GetPgLow8()),
13685 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013686 addr,
13687 is_signed);
13688}
13689
Alexandre Ramesd3832962016-07-04 15:03:43 +010013690void Simulator::DoUnreachable(const Instruction* instr) {
13691 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13692 (instr->GetImmException() == kUnreachableOpcode));
13693
13694 fprintf(stream_,
13695 "Hit UNREACHABLE marker at pc=%p.\n",
13696 reinterpret_cast<const void*>(instr));
13697 abort();
13698}
13699
13700
13701void Simulator::DoTrace(const Instruction* instr) {
13702 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13703 (instr->GetImmException() == kTraceOpcode));
13704
13705 // Read the arguments encoded inline in the instruction stream.
13706 uint32_t parameters;
13707 uint32_t command;
13708
13709 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13710 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13711 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13712
13713 switch (command) {
13714 case TRACE_ENABLE:
13715 SetTraceParameters(GetTraceParameters() | parameters);
13716 break;
13717 case TRACE_DISABLE:
13718 SetTraceParameters(GetTraceParameters() & ~parameters);
13719 break;
13720 default:
13721 VIXL_UNREACHABLE();
13722 }
13723
13724 WritePc(instr->GetInstructionAtOffset(kTraceLength));
13725}
13726
13727
13728void Simulator::DoLog(const Instruction* instr) {
13729 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13730 (instr->GetImmException() == kLogOpcode));
13731
13732 // Read the arguments encoded inline in the instruction stream.
13733 uint32_t parameters;
13734
13735 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13736 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13737
13738 // We don't support a one-shot LOG_DISASM.
13739 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13740 // Print the requested information.
13741 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13742 if (parameters & LOG_REGS) PrintRegisters();
13743 if (parameters & LOG_VREGS) PrintVRegisters();
13744
13745 WritePc(instr->GetInstructionAtOffset(kLogLength));
13746}
13747
13748
13749void Simulator::DoPrintf(const Instruction* instr) {
13750 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13751 (instr->GetImmException() == kPrintfOpcode));
13752
13753 // Read the arguments encoded inline in the instruction stream.
13754 uint32_t arg_count;
13755 uint32_t arg_pattern_list;
13756 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13757 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13758 memcpy(&arg_pattern_list,
13759 instr + kPrintfArgPatternListOffset,
13760 sizeof(arg_pattern_list));
13761
13762 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13763 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13764
13765 // We need to call the host printf function with a set of arguments defined by
13766 // arg_pattern_list. Because we don't know the types and sizes of the
13767 // arguments, this is very difficult to do in a robust and portable way. To
13768 // work around the problem, we pick apart the format string, and print one
13769 // format placeholder at a time.
13770
13771 // Allocate space for the format string. We take a copy, so we can modify it.
13772 // Leave enough space for one extra character per expected argument (plus the
13773 // '\0' termination).
13774 const char* format_base = ReadRegister<const char*>(0);
13775 VIXL_ASSERT(format_base != NULL);
13776 size_t length = strlen(format_base) + 1;
13777 char* const format = new char[length + arg_count];
13778
13779 // A list of chunks, each with exactly one format placeholder.
13780 const char* chunks[kPrintfMaxArgCount];
13781
13782 // Copy the format string and search for format placeholders.
13783 uint32_t placeholder_count = 0;
13784 char* format_scratch = format;
13785 for (size_t i = 0; i < length; i++) {
13786 if (format_base[i] != '%') {
13787 *format_scratch++ = format_base[i];
13788 } else {
13789 if (format_base[i + 1] == '%') {
13790 // Ignore explicit "%%" sequences.
13791 *format_scratch++ = format_base[i];
13792 i++;
13793 // Chunks after the first are passed as format strings to printf, so we
13794 // need to escape '%' characters in those chunks.
13795 if (placeholder_count > 0) *format_scratch++ = format_base[i];
13796 } else {
13797 VIXL_CHECK(placeholder_count < arg_count);
13798 // Insert '\0' before placeholders, and store their locations.
13799 *format_scratch++ = '\0';
13800 chunks[placeholder_count++] = format_scratch;
13801 *format_scratch++ = format_base[i];
13802 }
13803 }
13804 }
13805 VIXL_CHECK(placeholder_count == arg_count);
13806
13807 // Finally, call printf with each chunk, passing the appropriate register
13808 // argument. Normally, printf returns the number of bytes transmitted, so we
13809 // can emulate a single printf call by adding the result from each chunk. If
13810 // any call returns a negative (error) value, though, just return that value.
13811
13812 printf("%s", clr_printf);
13813
13814 // Because '\0' is inserted before each placeholder, the first string in
13815 // 'format' contains no format placeholders and should be printed literally.
13816 int result = printf("%s", format);
13817 int pcs_r = 1; // Start at x1. x0 holds the format string.
13818 int pcs_f = 0; // Start at d0.
13819 if (result >= 0) {
13820 for (uint32_t i = 0; i < placeholder_count; i++) {
13821 int part_result = -1;
13822
13823 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13824 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13825 switch (arg_pattern) {
13826 case kPrintfArgW:
13827 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13828 break;
13829 case kPrintfArgX:
13830 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13831 break;
13832 case kPrintfArgD:
13833 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13834 break;
13835 default:
13836 VIXL_UNREACHABLE();
13837 }
13838
13839 if (part_result < 0) {
13840 // Handle error values.
13841 result = part_result;
13842 break;
13843 }
13844
13845 result += part_result;
13846 }
13847 }
13848
13849 printf("%s", clr_normal);
13850
13851 // Printf returns its result in x0 (just like the C library's printf).
13852 WriteXRegister(0, result);
13853
13854 // The printf parameters are inlined in the code, so skip them.
13855 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13856
13857 // Set LR as if we'd just called a native printf function.
13858 WriteLr(ReadPc());
13859
13860 delete[] format;
13861}
13862
Alexandre Rames064e02d2016-07-12 11:53:13 +010013863
Alexandre Ramesca73ba02016-07-28 09:16:03 +010013864#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010013865void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013866 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013867 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13868 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013869 uintptr_t call_wrapper_address =
13870 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13871 uintptr_t function_address =
13872 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080013873 RuntimeCallType call_type = static_cast<RuntimeCallType>(
13874 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013875 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010013876 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013877
13878 if (call_type == kCallRuntime) {
13879 WriteRegister(kLinkRegCode,
13880 instr->GetInstructionAtOffset(kRuntimeCallLength));
13881 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013882 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013883 // Read the return address from `lr` and write it into `pc`.
13884 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013885}
13886#else
13887void Simulator::DoRuntimeCall(const Instruction* instr) {
13888 USE(instr);
13889 VIXL_UNREACHABLE();
13890}
13891#endif
13892
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013893
13894void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
13895 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
13896
13897 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013898 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013899 std::numeric_limits<ElementType>::max());
13900
13901 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
13902
13903 size_t element_size = sizeof(ElementType);
13904 size_t offset = kConfigureCPUFeaturesListOffset;
13905
13906 // Read the kNone-terminated list of features.
13907 CPUFeatures parameters;
13908 while (true) {
13909 ElementType feature = Memory::Read<ElementType>(instr + offset);
13910 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013911 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013912 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
13913 }
13914
13915 switch (instr->GetImmException()) {
13916 case kSetCPUFeaturesOpcode:
13917 SetCPUFeatures(parameters);
13918 break;
13919 case kEnableCPUFeaturesOpcode:
13920 GetCPUFeatures()->Combine(parameters);
13921 break;
13922 case kDisableCPUFeaturesOpcode:
13923 GetCPUFeatures()->Remove(parameters);
13924 break;
13925 default:
13926 VIXL_UNREACHABLE();
13927 break;
13928 }
13929
13930 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
13931}
13932
13933
13934void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
13935 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13936 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
13937 USE(instr);
13938
13939 saved_cpu_features_.push_back(*GetCPUFeatures());
13940}
13941
13942
13943void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
13944 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13945 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
13946 USE(instr);
13947
13948 SetCPUFeatures(saved_cpu_features_.back());
13949 saved_cpu_features_.pop_back();
13950}
13951
13952
Alexandre Ramesd3832962016-07-04 15:03:43 +010013953} // namespace aarch64
13954} // namespace vixl
13955
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010013956#endif // VIXL_INCLUDE_SIMULATOR_AARCH64