blob: 01f28b54188a0ebc6650de73c1049988a9bfc073 [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"):
2281 VIXL_UNIMPLEMENTED();
2282 break;
2283 case Hash("sqabs_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002284 abs(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002285 break;
2286 case Hash("sqneg_z_p_z"):
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002287 neg(vform, result, zn).SignedSaturate(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002288 break;
2289 default:
2290 VIXL_UNIMPLEMENTED();
2291 }
Martyn Capewell7ebf9cc2020-09-23 18:32:38 +01002292 mov_merging(vform, zd, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002293}
2294
2295void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
Martyn Capewell030875c2020-10-21 18:08:05 +01002296 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002297 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002298 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002299 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002300 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell030875c2020-10-21 18:08:05 +01002301 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002302
Martyn Capewell030875c2020-10-21 18:08:05 +01002303 VIXL_ASSERT(form_hash_ == Hash("histcnt_z_p_zz"));
2304 if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
Martyn Capewell710ec6f2020-10-22 16:56:17 +01002305 histogram(vform, result, pg, zn, zm);
Martyn Capewell030875c2020-10-21 18:08:05 +01002306 mov_zeroing(vform, zd, pg, result);
2307 } else {
2308 VIXL_UNIMPLEMENTED();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002309 }
2310}
2311
Martyn Capewell6bf28752020-08-05 11:57:06 +01002312void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002313 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002314 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002315 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002316 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002317 SimVRegister result;
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002318 bool do_bext = false;
2319
Martyn Capewell6bf28752020-08-05 11:57:06 +01002320 switch (form_hash_) {
2321 case Hash("bdep_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002322 bdep(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002323 break;
2324 case Hash("bext_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002325 do_bext = true;
2326 VIXL_FALLTHROUGH();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002327 case Hash("bgrp_z_zz"):
Martyn Capewell507dd4e2020-10-20 17:44:00 +01002328 bgrp(vform, zd, zn, zm, do_bext);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002329 break;
2330 case Hash("eorbt_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002331 rotate_elements_right(vform, result, zm, 1);
2332 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2333 mov_alternating(vform, zd, result, 0);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002334 break;
2335 case Hash("eortb_z_zz"):
Martyn Capewellcd14aeb2020-09-18 10:53:59 +01002336 rotate_elements_right(vform, result, zm, -1);
2337 SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2338 mov_alternating(vform, zd, result, 1);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002339 break;
2340 case Hash("mul_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002341 mul(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002342 break;
2343 case Hash("smulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002344 smulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002345 break;
2346 case Hash("sqdmulh_z_zz"):
Martyn Capewell310326b2021-01-12 16:33:22 +00002347 sqdmulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002348 break;
2349 case Hash("sqrdmulh_z_zz"):
Martyn Capewell310326b2021-01-12 16:33:22 +00002350 sqrdmulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002351 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002352 case Hash("umulh_z_zz"):
TatWai Chong1dba0fb2020-10-07 16:50:13 -07002353 umulh(vform, zd, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002354 break;
2355 default:
2356 VIXL_UNIMPLEMENTED();
2357 }
2358}
2359
2360void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002361 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002362 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002363 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002364 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002365
2366 SimVRegister zm_b, zm_t;
TatWai Chong236e7ae2020-09-13 14:55:04 -07002367 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2368 pack_even_elements(vform_half, zm_b, zm);
2369 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002370
2371 switch (form_hash_) {
2372 case Hash("saddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002373 saddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002374 break;
2375 case Hash("saddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002376 saddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002377 break;
2378 case Hash("ssubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002379 ssubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002380 break;
2381 case Hash("ssubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002382 ssubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002383 break;
2384 case Hash("uaddwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002385 uaddw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002386 break;
2387 case Hash("uaddwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002388 uaddw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002389 break;
2390 case Hash("usubwb_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002391 usubw(vform, zd, zn, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002392 break;
2393 case Hash("usubwt_z_zz"):
Martyn Capewell7cf66e82020-09-25 15:54:31 +01002394 usubw(vform, zd, zn, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002395 break;
2396 default:
2397 VIXL_UNIMPLEMENTED();
2398 }
2399}
2400
2401void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2402 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002403 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell78743b62020-09-09 11:08:57 +01002404
2405 std::pair<int, int> shift_and_lane_size =
2406 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2407 int lane_size = shift_and_lane_size.second;
2408 VIXL_ASSERT((lane_size >= 0) &&
2409 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2410 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2411 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002412
2413 switch (form_hash_) {
2414 case Hash("sli_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002415 // Shift distance is computed differently for left shifts. Convert the
2416 // result.
2417 shift_dist = (8 << lane_size) - shift_dist;
2418 sli(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002419 break;
2420 case Hash("sri_z_zzi"):
Martyn Capewell78743b62020-09-09 11:08:57 +01002421 sri(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002422 break;
2423 default:
2424 VIXL_UNIMPLEMENTED();
2425 }
2426}
2427
Martyn Capewellea9b4072020-10-09 11:25:26 +01002428void Simulator::SimulateSVENarrow(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002429 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002430 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellb5636e52020-09-17 11:21:29 +01002431 SimVRegister result;
2432
2433 std::pair<int, int> shift_and_lane_size =
2434 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2435 int lane_size = shift_and_lane_size.second;
2436 VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2437 (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2438 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewellea9b4072020-10-09 11:25:26 +01002439 int right_shift_dist = shift_and_lane_size.first;
Martyn Capewellb5636e52020-09-17 11:21:29 +01002440 bool top = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002441
2442 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002443 case Hash("sqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002444 top = true;
2445 VIXL_FALLTHROUGH();
2446 case Hash("sqxtnb_z_zz"):
2447 sqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002448 break;
2449 case Hash("sqxtunt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002450 top = true;
2451 VIXL_FALLTHROUGH();
2452 case Hash("sqxtunb_z_zz"):
2453 sqxtun(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002454 break;
2455 case Hash("uqxtnt_z_zz"):
Martyn Capewellb5636e52020-09-17 11:21:29 +01002456 top = true;
2457 VIXL_FALLTHROUGH();
2458 case Hash("uqxtnb_z_zz"):
2459 uqxtn(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002460 break;
Martyn Capewellea9b4072020-10-09 11:25:26 +01002461 case Hash("rshrnt_z_zi"):
2462 top = true;
2463 VIXL_FALLTHROUGH();
2464 case Hash("rshrnb_z_zi"):
2465 rshrn(vform, result, zn, right_shift_dist);
2466 break;
2467 case Hash("shrnt_z_zi"):
2468 top = true;
2469 VIXL_FALLTHROUGH();
2470 case Hash("shrnb_z_zi"):
2471 shrn(vform, result, zn, right_shift_dist);
2472 break;
2473 case Hash("sqrshrnt_z_zi"):
2474 top = true;
2475 VIXL_FALLTHROUGH();
2476 case Hash("sqrshrnb_z_zi"):
2477 sqrshrn(vform, result, zn, right_shift_dist);
2478 break;
2479 case Hash("sqrshrunt_z_zi"):
2480 top = true;
2481 VIXL_FALLTHROUGH();
2482 case Hash("sqrshrunb_z_zi"):
2483 sqrshrun(vform, result, zn, right_shift_dist);
2484 break;
2485 case Hash("sqshrnt_z_zi"):
2486 top = true;
2487 VIXL_FALLTHROUGH();
2488 case Hash("sqshrnb_z_zi"):
2489 sqshrn(vform, result, zn, right_shift_dist);
2490 break;
2491 case Hash("sqshrunt_z_zi"):
2492 top = true;
2493 VIXL_FALLTHROUGH();
2494 case Hash("sqshrunb_z_zi"):
2495 sqshrun(vform, result, zn, right_shift_dist);
2496 break;
2497 case Hash("uqrshrnt_z_zi"):
2498 top = true;
2499 VIXL_FALLTHROUGH();
2500 case Hash("uqrshrnb_z_zi"):
2501 uqrshrn(vform, result, zn, right_shift_dist);
2502 break;
2503 case Hash("uqshrnt_z_zi"):
2504 top = true;
2505 VIXL_FALLTHROUGH();
2506 case Hash("uqshrnb_z_zi"):
2507 uqshrn(vform, result, zn, right_shift_dist);
2508 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002509 default:
2510 VIXL_UNIMPLEMENTED();
2511 }
Martyn Capewellb5636e52020-09-17 11:21:29 +01002512
2513 if (top) {
2514 // Keep even elements, replace odd elements with the results.
2515 xtn(vform, zd, zd);
2516 zip1(vform, zd, zd, result);
2517 } else {
2518 // Zero odd elements, replace even elements with the results.
2519 SimVRegister zero;
2520 zero.Clear();
2521 zip1(vform, zd, result, zero);
2522 }
Martyn Capewell6bf28752020-08-05 11:57:06 +01002523}
2524
Martyn Capewellc7275e62020-09-24 14:06:07 +01002525void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
Martyn Capewella2d7fbb2020-09-18 18:22:54 +01002526 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002527 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002528 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002529 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002530 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2531
2532 // Construct temporary registers containing the even (bottom) and odd (top)
2533 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002534 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2535 pack_even_elements(vform_half, zn_b, zn);
2536 pack_even_elements(vform_half, zm_b, zm);
2537 pack_odd_elements(vform_half, zn_t, zn);
2538 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewellc7275e62020-09-24 14:06:07 +01002539
2540 switch (form_hash_) {
2541 case Hash("sabdlb_z_zz"):
2542 sabdl(vform, zd, zn_b, zm_b);
2543 break;
2544 case Hash("sabdlt_z_zz"):
2545 sabdl(vform, zd, zn_t, zm_t);
2546 break;
2547 case Hash("saddlb_z_zz"):
2548 saddl(vform, zd, zn_b, zm_b);
2549 break;
2550 case Hash("saddlbt_z_zz"):
2551 saddl(vform, zd, zn_b, zm_t);
2552 break;
2553 case Hash("saddlt_z_zz"):
2554 saddl(vform, zd, zn_t, zm_t);
2555 break;
2556 case Hash("ssublb_z_zz"):
2557 ssubl(vform, zd, zn_b, zm_b);
2558 break;
2559 case Hash("ssublbt_z_zz"):
2560 ssubl(vform, zd, zn_b, zm_t);
2561 break;
2562 case Hash("ssublt_z_zz"):
2563 ssubl(vform, zd, zn_t, zm_t);
2564 break;
2565 case Hash("ssubltb_z_zz"):
2566 ssubl(vform, zd, zn_t, zm_b);
2567 break;
2568 case Hash("uabdlb_z_zz"):
2569 uabdl(vform, zd, zn_b, zm_b);
2570 break;
2571 case Hash("uabdlt_z_zz"):
2572 uabdl(vform, zd, zn_t, zm_t);
2573 break;
2574 case Hash("uaddlb_z_zz"):
2575 uaddl(vform, zd, zn_b, zm_b);
2576 break;
2577 case Hash("uaddlt_z_zz"):
2578 uaddl(vform, zd, zn_t, zm_t);
2579 break;
2580 case Hash("usublb_z_zz"):
2581 usubl(vform, zd, zn_b, zm_b);
2582 break;
2583 case Hash("usublt_z_zz"):
2584 usubl(vform, zd, zn_t, zm_t);
2585 break;
Martyn Capewell67d2f822020-10-13 16:39:33 +01002586 case Hash("sabalb_z_zzz"):
2587 sabal(vform, zd, zn_b, zm_b);
2588 break;
2589 case Hash("sabalt_z_zzz"):
2590 sabal(vform, zd, zn_t, zm_t);
2591 break;
2592 case Hash("uabalb_z_zzz"):
2593 uabal(vform, zd, zn_b, zm_b);
2594 break;
2595 case Hash("uabalt_z_zzz"):
2596 uabal(vform, zd, zn_t, zm_t);
2597 break;
Martyn Capewellc7275e62020-09-24 14:06:07 +01002598 default:
2599 VIXL_UNIMPLEMENTED();
2600 }
2601}
2602
TatWai Chong236e7ae2020-09-13 14:55:04 -07002603void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2604 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewellc7275e62020-09-24 14:06:07 +01002605 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002606 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellc7275e62020-09-24 14:06:07 +01002607 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong236e7ae2020-09-13 14:55:04 -07002608 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2609 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2610 pack_even_elements(vform_half, zn_b, zn);
2611 pack_even_elements(vform_half, zm_b, zm);
2612 pack_odd_elements(vform_half, zn_t, zn);
2613 pack_odd_elements(vform_half, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002614
2615 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002616 case Hash("pmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002617 // '00' is reserved for Q-sized lane.
2618 if (vform == kFormatVnB) {
2619 VIXL_UNIMPLEMENTED();
2620 }
2621 pmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002622 break;
2623 case Hash("pmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002624 // '00' is reserved for Q-sized lane.
2625 if (vform == kFormatVnB) {
2626 VIXL_UNIMPLEMENTED();
2627 }
2628 pmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002629 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002630 case Hash("smullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002631 smull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002632 break;
2633 case Hash("smullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002634 smull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002635 break;
2636 case Hash("sqdmullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002637 sqdmull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002638 break;
2639 case Hash("sqdmullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002640 sqdmull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002641 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002642 case Hash("umullb_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002643 umull(vform, zd, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002644 break;
2645 case Hash("umullt_z_zz"):
TatWai Chong236e7ae2020-09-13 14:55:04 -07002646 umull(vform, zd, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002647 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002648 default:
2649 VIXL_UNIMPLEMENTED();
2650 }
2651}
2652
Martyn Capewell8b9c44b2020-10-14 18:21:42 +01002653void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2654 SimVRegister& zd = ReadVRegister(instr->GetRd());
2655 SimVRegister& zm = ReadVRegister(instr->GetRm());
2656 SimVRegister& zn = ReadVRegister(instr->GetRn());
2657 SimVRegister result;
2658 bool top = false;
2659
2660 VectorFormat vform_src = instr->GetSVEVectorFormat();
2661 if (vform_src == kFormatVnB) {
2662 VIXL_UNIMPLEMENTED();
2663 }
2664 VectorFormat vform = VectorFormatHalfWidth(vform_src);
2665
2666 switch (form_hash_) {
2667 case Hash("addhnt_z_zz"):
2668 top = true;
2669 VIXL_FALLTHROUGH();
2670 case Hash("addhnb_z_zz"):
2671 addhn(vform, result, zn, zm);
2672 break;
2673 case Hash("raddhnt_z_zz"):
2674 top = true;
2675 VIXL_FALLTHROUGH();
2676 case Hash("raddhnb_z_zz"):
2677 raddhn(vform, result, zn, zm);
2678 break;
2679 case Hash("rsubhnt_z_zz"):
2680 top = true;
2681 VIXL_FALLTHROUGH();
2682 case Hash("rsubhnb_z_zz"):
2683 rsubhn(vform, result, zn, zm);
2684 break;
2685 case Hash("subhnt_z_zz"):
2686 top = true;
2687 VIXL_FALLTHROUGH();
2688 case Hash("subhnb_z_zz"):
2689 subhn(vform, result, zn, zm);
2690 break;
2691 default:
2692 VIXL_UNIMPLEMENTED();
2693 }
2694
2695 if (top) {
2696 // Keep even elements, replace odd elements with the results.
2697 xtn(vform, zd, zd);
2698 zip1(vform, zd, zd, result);
2699 } else {
2700 // Zero odd elements, replace even elements with the results.
2701 SimVRegister zero;
2702 zero.Clear();
2703 zip1(vform, zd, result, zero);
2704 }
2705}
2706
Martyn Capewellea9b4072020-10-09 11:25:26 +01002707void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002708 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002709 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell51dcef92020-10-08 16:04:12 +01002710 SimVRegister zn_b, zn_t;
2711
2712 std::pair<int, int> shift_and_lane_size =
2713 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2714 int lane_size = shift_and_lane_size.second;
2715 VIXL_ASSERT((lane_size >= 0) &&
2716 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2717 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2718 int right_shift_dist = shift_and_lane_size.first;
2719 int left_shift_dist = (8 << lane_size) - right_shift_dist;
2720
2721 // Construct temporary registers containing the even (bottom) and odd (top)
2722 // elements.
TatWai Chong236e7ae2020-09-13 14:55:04 -07002723 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2724 pack_even_elements(vform_half, zn_b, zn);
2725 pack_odd_elements(vform_half, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002726
2727 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002728 case Hash("sshllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002729 sshll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002730 break;
2731 case Hash("sshllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002732 sshll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002733 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002734 case Hash("ushllb_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002735 ushll(vform, zd, zn_b, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002736 break;
2737 case Hash("ushllt_z_zi"):
Martyn Capewell51dcef92020-10-08 16:04:12 +01002738 ushll(vform, zd, zn_t, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002739 break;
2740 default:
2741 VIXL_UNIMPLEMENTED();
2742 }
2743}
2744
2745void Simulator::Simulate_ZdaD_ZnD_ZmD_imm(const Instruction* instr) {
2746 SimVRegister& zda = ReadVRegister(instr->GetRd());
2747 USE(zda);
2748 SimVRegister& zn = ReadVRegister(instr->GetRn());
2749 USE(zn);
2750
2751 switch (form_hash_) {
2752 case Hash("mla_z_zzzi_d"):
2753 VIXL_UNIMPLEMENTED();
2754 break;
2755 case Hash("mls_z_zzzi_d"):
2756 VIXL_UNIMPLEMENTED();
2757 break;
2758 case Hash("sqrdmlah_z_zzzi_d"):
2759 VIXL_UNIMPLEMENTED();
2760 break;
2761 case Hash("sqrdmlsh_z_zzzi_d"):
2762 VIXL_UNIMPLEMENTED();
2763 break;
2764 default:
2765 VIXL_UNIMPLEMENTED();
2766 }
2767}
2768
Martyn Capewell6bf28752020-08-05 11:57:06 +01002769void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2770 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002771 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong05545662020-12-18 20:53:05 -08002772 SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
2773
2774 SimVRegister temp, zm_idx, zn_b, zn_t;
2775 Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
2776 dup_elements_to_segments(kFormatVnS, temp, zm, index);
2777 pack_even_elements(kFormatVnS, zm_idx, temp);
2778 pack_even_elements(kFormatVnS, zn_b, zn);
2779 pack_odd_elements(kFormatVnS, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002780
2781 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002782 case Hash("sqdmlalb_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002783 sqdmlal(kFormatVnD, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002784 break;
2785 case Hash("sqdmlalt_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002786 sqdmlal(kFormatVnD, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002787 break;
2788 case Hash("sqdmlslb_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002789 sqdmlsl(kFormatVnD, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002790 break;
2791 case Hash("sqdmlslt_z_zzzi_d"):
TatWai Chong05545662020-12-18 20:53:05 -08002792 sqdmlsl(kFormatVnD, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002793 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002794 default:
2795 VIXL_UNIMPLEMENTED();
2796 }
2797}
2798
2799void Simulator::Simulate_ZdaH_ZnH_ZmH_imm(const Instruction* instr) {
2800 SimVRegister& zda = ReadVRegister(instr->GetRd());
2801 USE(zda);
2802 SimVRegister& zn = ReadVRegister(instr->GetRn());
2803 USE(zn);
2804
2805 switch (form_hash_) {
2806 case Hash("mla_z_zzzi_h"):
2807 VIXL_UNIMPLEMENTED();
2808 break;
2809 case Hash("mls_z_zzzi_h"):
2810 VIXL_UNIMPLEMENTED();
2811 break;
2812 case Hash("sqrdmlah_z_zzzi_h"):
2813 VIXL_UNIMPLEMENTED();
2814 break;
2815 case Hash("sqrdmlsh_z_zzzi_h"):
2816 VIXL_UNIMPLEMENTED();
2817 break;
2818 default:
2819 VIXL_UNIMPLEMENTED();
2820 }
2821}
2822
Martyn Capewell6bf28752020-08-05 11:57:06 +01002823void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2824 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002825 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002826 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chongba9a1482020-10-01 20:25:54 -07002827
2828 SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2829 pack_even_elements(kFormatVnH, zn_b, zn);
2830 pack_even_elements(kFormatVnH, zm_b, zm);
2831 pack_odd_elements(kFormatVnH, zn_t, zn);
2832 pack_odd_elements(kFormatVnH, zm_t, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002833
2834 switch (form_hash_) {
2835 case Hash("fmlalb_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002836 fmlal(kFormatVnS, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002837 break;
2838 case Hash("fmlalt_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002839 fmlal(kFormatVnS, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002840 break;
2841 case Hash("fmlslb_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002842 fmlsl(kFormatVnS, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002843 break;
2844 case Hash("fmlslt_z_zzz"):
TatWai Chongba9a1482020-10-01 20:25:54 -07002845 fmlsl(kFormatVnS, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002846 break;
2847 default:
2848 VIXL_UNIMPLEMENTED();
2849 }
2850}
2851
2852void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2853 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002854 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong05545662020-12-18 20:53:05 -08002855 SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
2856
2857 SimVRegister temp, zm_idx, zn_b, zn_t;
2858 Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
2859 dup_elements_to_segments(kFormatVnH, temp, zm, index);
2860 pack_even_elements(kFormatVnH, zm_idx, temp);
2861 pack_even_elements(kFormatVnH, zn_b, zn);
2862 pack_odd_elements(kFormatVnH, zn_t, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002863
2864 switch (form_hash_) {
2865 case Hash("fmlalb_z_zzzi_s"):
2866 VIXL_UNIMPLEMENTED();
2867 break;
2868 case Hash("fmlalt_z_zzzi_s"):
2869 VIXL_UNIMPLEMENTED();
2870 break;
2871 case Hash("fmlslb_z_zzzi_s"):
2872 VIXL_UNIMPLEMENTED();
2873 break;
2874 case Hash("fmlslt_z_zzzi_s"):
2875 VIXL_UNIMPLEMENTED();
2876 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002877 case Hash("sqdmlalb_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002878 sqdmlal(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002879 break;
2880 case Hash("sqdmlalt_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002881 sqdmlal(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002882 break;
2883 case Hash("sqdmlslb_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002884 sqdmlsl(kFormatVnS, zda, zn_b, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002885 break;
2886 case Hash("sqdmlslt_z_zzzi_s"):
TatWai Chong05545662020-12-18 20:53:05 -08002887 sqdmlsl(kFormatVnS, zda, zn_t, zm_idx);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002888 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002889 default:
2890 VIXL_UNIMPLEMENTED();
2891 }
2892}
2893
2894void Simulator::Simulate_ZdaS_ZnS_ZmS_imm(const Instruction* instr) {
2895 SimVRegister& zda = ReadVRegister(instr->GetRd());
2896 USE(zda);
2897 SimVRegister& zn = ReadVRegister(instr->GetRn());
2898 USE(zn);
2899
2900 switch (form_hash_) {
2901 case Hash("mla_z_zzzi_s"):
2902 VIXL_UNIMPLEMENTED();
2903 break;
2904 case Hash("mls_z_zzzi_s"):
2905 VIXL_UNIMPLEMENTED();
2906 break;
2907 case Hash("sqrdmlah_z_zzzi_s"):
2908 VIXL_UNIMPLEMENTED();
2909 break;
2910 case Hash("sqrdmlsh_z_zzzi_s"):
2911 VIXL_UNIMPLEMENTED();
2912 break;
2913 default:
2914 VIXL_UNIMPLEMENTED();
2915 }
2916}
2917
Martyn Capewell6bf28752020-08-05 11:57:06 +01002918void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
TatWai Chong602aa122020-10-05 16:28:27 -07002919 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002920 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002921 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002922 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chong602aa122020-10-05 16:28:27 -07002923 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002924
2925 switch (form_hash_) {
2926 case Hash("sadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002927 sadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002928 break;
2929 case Hash("uadalp_z_p_z"):
TatWai Chong602aa122020-10-05 16:28:27 -07002930 uadalp(vform, result, zn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002931 break;
2932 default:
2933 VIXL_UNIMPLEMENTED();
2934 }
TatWai Chong602aa122020-10-05 16:28:27 -07002935 mov_merging(vform, zda, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002936}
2937
Martyn Capewellc4b56bb2020-10-14 15:45:14 +01002938void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
2939 VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
2940 SimVRegister& zda = ReadVRegister(instr->GetRd());
2941 SimVRegister& zm = ReadVRegister(instr->GetRm());
2942 SimVRegister& zn = ReadVRegister(instr->GetRn());
2943
2944 SimVRegister not_zn;
2945 not_(vform, not_zn, zn);
2946
2947 switch (form_hash_) {
2948 case Hash("adclb_z_zzz"):
2949 adcl(vform, zda, zn, zm, /* top = */ false);
2950 break;
2951 case Hash("adclt_z_zzz"):
2952 adcl(vform, zda, zn, zm, /* top = */ true);
2953 break;
2954 case Hash("sbclb_z_zzz"):
2955 adcl(vform, zda, not_zn, zm, /* top = */ false);
2956 break;
2957 case Hash("sbclt_z_zzz"):
2958 adcl(vform, zda, not_zn, zm, /* top = */ true);
2959 break;
2960 default:
2961 VIXL_UNIMPLEMENTED();
2962 }
2963}
2964
Martyn Capewell6bf28752020-08-05 11:57:06 +01002965void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002966 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01002967 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002968 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002969 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002970
2971 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002972 case Hash("saba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002973 saba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002974 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01002975 case Hash("sqrdmlah_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07002976 sqrdmlah(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002977 break;
2978 case Hash("sqrdmlsh_z_zzz"):
TatWai Chongefbd8792020-10-02 16:05:47 -07002979 sqrdmlsh(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002980 break;
2981 case Hash("uaba_z_zzz"):
Martyn Capewelleb37ef32020-09-09 16:46:41 +01002982 uaba(vform, zda, zn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01002983 break;
2984 default:
2985 VIXL_UNIMPLEMENTED();
2986 }
2987}
2988
TatWai Chongada6b352020-11-06 13:48:09 -08002989void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01002990 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002991 SimVRegister& zn = ReadVRegister(instr->GetRn());
TatWai Chongada6b352020-11-06 13:48:09 -08002992 int rot = instr->ExtractBits(11, 10) * 90;
TatWai Chong6b67f6e2020-12-03 23:37:57 -08002993 // The information below are only valid for the vector form of instruction.
2994 VectorFormat vform = instr->GetSVEVectorFormat();
2995 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01002996
2997 switch (form_hash_) {
2998 case Hash("cmla_z_zzz"):
TatWai Chongada6b352020-11-06 13:48:09 -08002999 cmla(vform, zda, zda, zn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003000 break;
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003001 case Hash("cmla_z_zzzi_h"):
3002 VIXL_UNIMPLEMENTED();
3003 break;
3004 case Hash("cmla_z_zzzi_s"):
3005 VIXL_UNIMPLEMENTED();
3006 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003007 case Hash("sqrdcmlah_z_zzz"):
TatWai Chongada6b352020-11-06 13:48:09 -08003008 sqrdcmlah(vform, zda, zda, zn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003009 break;
TatWai Chong6b67f6e2020-12-03 23:37:57 -08003010 case Hash("sqrdcmlah_z_zzzi_h"):
3011 sqrdcmlah(kFormatVnH,
3012 zda,
3013 zda,
3014 zn,
3015 ReadVRegister(instr->ExtractBits(18, 16)),
3016 instr->ExtractBits(20, 19),
3017 rot);
3018 break;
3019 case Hash("sqrdcmlah_z_zzzi_s"):
3020 sqrdcmlah(kFormatVnS,
3021 zda,
3022 zda,
3023 zn,
3024 ReadVRegister(instr->ExtractBits(19, 16)),
3025 instr->ExtractBit(20),
3026 rot);
3027 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003028 default:
3029 VIXL_UNIMPLEMENTED();
3030 }
3031}
3032
3033void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003034 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003035 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003036
3037 std::pair<int, int> shift_and_lane_size =
3038 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3039 int lane_size = shift_and_lane_size.second;
3040 VIXL_ASSERT((lane_size >= 0) &&
3041 (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3042 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3043 int shift_dist = shift_and_lane_size.first;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003044
3045 switch (form_hash_) {
3046 case Hash("srsra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003047 srsra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003048 break;
3049 case Hash("ssra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003050 ssra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003051 break;
3052 case Hash("ursra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003053 ursra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003054 break;
3055 case Hash("usra_z_zi"):
Martyn Capewell3a3560f2020-09-11 15:32:08 +01003056 usra(vform, zd, zn, shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003057 break;
3058 default:
3059 VIXL_UNIMPLEMENTED();
3060 }
3061}
3062
3063void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
Martyn Capewell4a454b42020-11-19 18:18:10 +00003064 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003065 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003066 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003067 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell4a454b42020-11-19 18:18:10 +00003068
TatWai Chong5c080292020-12-13 03:57:15 -08003069 SimVRegister zero, zn_b, zm_b, zn_t, zm_t;
3070 zero.Clear();
3071
Martyn Capewell4a454b42020-11-19 18:18:10 +00003072 VectorFormat vform_half = VectorFormatHalfWidth(vform);
TatWai Chong5c080292020-12-13 03:57:15 -08003073 uzp1(vform_half, zn_b, zn, zero);
3074 uzp1(vform_half, zm_b, zm, zero);
3075 uzp2(vform_half, zn_t, zn, zero);
3076 uzp2(vform_half, zm_t, zm, zero);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003077
3078 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003079 case Hash("smlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003080 smlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003081 break;
3082 case Hash("smlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003083 smlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003084 break;
3085 case Hash("smlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003086 smlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003087 break;
3088 case Hash("smlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003089 smlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003090 break;
3091 case Hash("sqdmlalb_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003092 sqdmlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003093 break;
3094 case Hash("sqdmlalbt_z_zzz"):
TatWai Chong5c080292020-12-13 03:57:15 -08003095 sqdmlal(vform, zda, zn_b, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003096 break;
3097 case Hash("sqdmlalt_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003098 sqdmlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003099 break;
3100 case Hash("sqdmlslb_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003101 sqdmlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003102 break;
3103 case Hash("sqdmlslbt_z_zzz"):
TatWai Chong5c080292020-12-13 03:57:15 -08003104 sqdmlsl(vform, zda, zn_b, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003105 break;
3106 case Hash("sqdmlslt_z_zzz"):
TatWai Chong3cb35a62020-12-05 21:22:08 -08003107 sqdmlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003108 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003109 case Hash("umlalb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003110 umlal(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003111 break;
3112 case Hash("umlalt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003113 umlal(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003114 break;
3115 case Hash("umlslb_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003116 umlsl(vform, zda, zn_b, zm_b);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003117 break;
3118 case Hash("umlslt_z_zzz"):
Martyn Capewell4a454b42020-11-19 18:18:10 +00003119 umlsl(vform, zda, zn_t, zm_t);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003120 break;
3121 default:
3122 VIXL_UNIMPLEMENTED();
3123 }
3124}
3125
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003126void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
Martyn Capewellf4da2202020-11-03 17:42:57 +00003127 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003128 SimVRegister& zda = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003129 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewellf4da2202020-11-03 17:42:57 +00003130 int rot = instr->ExtractBits(11, 10) * 90;
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003131 unsigned zm_code = instr->GetRm();
3132 int index = -1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003133
3134 switch (form_hash_) {
3135 case Hash("cdot_z_zzz"):
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003136 // Nothing to do.
3137 break;
3138 case Hash("cdot_z_zzzi_s"):
3139 index = zm_code >> 3;
3140 zm_code &= 0x7;
3141 break;
3142 case Hash("cdot_z_zzzi_d"):
3143 index = zm_code >> 4;
3144 zm_code &= 0xf;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003145 break;
3146 default:
3147 VIXL_UNIMPLEMENTED();
3148 }
Martyn Capewell1bb3f1a2020-11-04 18:54:02 +00003149
3150 SimVRegister temp;
3151 SimVRegister& zm = ReadVRegister(zm_code);
3152 if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3153 cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003154}
3155
Martyn Capewellb1b95782020-10-23 15:59:49 +01003156void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3157 VectorFormat vform = kFormatVnD;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003158 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003159 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewellb1b95782020-10-23 15:59:49 +01003160 SimVRegister& zk = ReadVRegister(instr->GetRn());
3161 SimVRegister temp;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003162
3163 switch (form_hash_) {
3164 case Hash("bcax_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003165 bic(vform, temp, zm, zk);
3166 eor(vform, zdn, temp, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003167 break;
3168 case Hash("bsl1n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003169 not_(vform, temp, zdn);
3170 bsl(vform, zdn, zk, temp, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003171 break;
3172 case Hash("bsl2n_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003173 not_(vform, temp, zm);
3174 bsl(vform, zdn, zk, zdn, temp);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003175 break;
3176 case Hash("bsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003177 bsl(vform, zdn, zk, zdn, zm);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003178 break;
3179 case Hash("eor3_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003180 eor(vform, temp, zdn, zm);
3181 eor(vform, zdn, temp, zk);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003182 break;
3183 case Hash("nbsl_z_zzz"):
Martyn Capewellb1b95782020-10-23 15:59:49 +01003184 bsl(vform, zdn, zk, zdn, zm);
3185 not_(vform, zdn, zdn);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003186 break;
3187 default:
3188 VIXL_UNIMPLEMENTED();
3189 }
3190}
3191
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003192void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3193 VectorFormat vform = instr->GetSVEVectorFormat();
3194 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3195 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3196 SimVRegister& zm = ReadVRegister(instr->GetRn());
3197 SimVRegister result;
3198
3199 switch (form_hash_) {
3200 case Hash("shadd_z_p_zz"):
3201 add(vform, result, zdn, zm).Halve(vform);
3202 break;
3203 case Hash("shsub_z_p_zz"):
3204 sub(vform, result, zdn, zm).Halve(vform);
3205 break;
3206 case Hash("shsubr_z_p_zz"):
3207 sub(vform, result, zm, zdn).Halve(vform);
3208 break;
3209 case Hash("srhadd_z_p_zz"):
3210 add(vform, result, zdn, zm).Halve(vform).Round(vform);
3211 break;
3212 case Hash("uhadd_z_p_zz"):
3213 add(vform, result, zdn, zm).Uhalve(vform);
3214 break;
3215 case Hash("uhsub_z_p_zz"):
3216 sub(vform, result, zdn, zm).Uhalve(vform);
3217 break;
3218 case Hash("uhsubr_z_p_zz"):
3219 sub(vform, result, zm, zdn).Uhalve(vform);
3220 break;
3221 case Hash("urhadd_z_p_zz"):
3222 add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3223 break;
3224 default:
3225 VIXL_UNIMPLEMENTED();
Martyn Capewell9b532192020-09-15 16:20:11 +01003226 break;
3227 }
3228 mov_merging(vform, zdn, pg, result);
3229}
3230
3231void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3232 VectorFormat vform = instr->GetSVEVectorFormat();
3233 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3234 SimVRegister& zm = ReadVRegister(instr->GetRn());
3235 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3236 SimVRegister result;
3237
3238 switch (form_hash_) {
3239 case Hash("sqadd_z_p_zz"):
3240 add(vform, result, zdn, zm).SignedSaturate(vform);
3241 break;
3242 case Hash("sqsub_z_p_zz"):
3243 sub(vform, result, zdn, zm).SignedSaturate(vform);
3244 break;
3245 case Hash("sqsubr_z_p_zz"):
3246 sub(vform, result, zm, zdn).SignedSaturate(vform);
3247 break;
3248 case Hash("suqadd_z_p_zz"):
3249 suqadd(vform, result, zdn, zm);
3250 break;
3251 case Hash("uqadd_z_p_zz"):
3252 add(vform, result, zdn, zm).UnsignedSaturate(vform);
3253 break;
3254 case Hash("uqsub_z_p_zz"):
3255 sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3256 break;
3257 case Hash("uqsubr_z_p_zz"):
3258 sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3259 break;
3260 case Hash("usqadd_z_p_zz"):
3261 usqadd(vform, result, zdn, zm);
3262 break;
3263 default:
3264 VIXL_UNIMPLEMENTED();
3265 break;
Martyn Capewell4e1980d2020-09-04 11:22:41 +01003266 }
3267 mov_merging(vform, zdn, pg, result);
3268}
3269
Martyn Capewellfa1e2112020-09-16 16:53:09 +01003270void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3271 VectorFormat vform = instr->GetSVEVectorFormat();
3272 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3273 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3274 SimVRegister& zm = ReadVRegister(instr->GetRn());
3275 SimVRegister result;
3276
3277 switch (form_hash_) {
3278 case Hash("addp_z_p_zz"):
3279 addp(vform, result, zdn, zm);
3280 break;
3281 case Hash("smaxp_z_p_zz"):
3282 smaxp(vform, result, zdn, zm);
3283 break;
3284 case Hash("sminp_z_p_zz"):
3285 sminp(vform, result, zdn, zm);
3286 break;
3287 case Hash("umaxp_z_p_zz"):
3288 umaxp(vform, result, zdn, zm);
3289 break;
3290 case Hash("uminp_z_p_zz"):
3291 uminp(vform, result, zdn, zm);
3292 break;
3293 default:
3294 VIXL_UNIMPLEMENTED();
3295 break;
3296 }
3297 mov_merging(vform, zdn, pg, result);
3298}
3299
Martyn Capewell6bf28752020-08-05 11:57:06 +01003300void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3301 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3302 USE(pg);
3303 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3304 USE(zdn);
3305 SimVRegister& zm = ReadVRegister(instr->GetRn());
3306 USE(zm);
3307
3308 switch (form_hash_) {
Martyn Capewell6bf28752020-08-05 11:57:06 +01003309 case Hash("faddp_z_p_zz"):
3310 VIXL_UNIMPLEMENTED();
3311 break;
3312 case Hash("fmaxnmp_z_p_zz"):
3313 VIXL_UNIMPLEMENTED();
3314 break;
3315 case Hash("fmaxp_z_p_zz"):
3316 VIXL_UNIMPLEMENTED();
3317 break;
3318 case Hash("fminnmp_z_p_zz"):
3319 VIXL_UNIMPLEMENTED();
3320 break;
3321 case Hash("fminp_z_p_zz"):
3322 VIXL_UNIMPLEMENTED();
3323 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003324 case Hash("sqrshl_z_p_zz"):
3325 VIXL_UNIMPLEMENTED();
3326 break;
3327 case Hash("sqrshlr_z_p_zz"):
3328 VIXL_UNIMPLEMENTED();
3329 break;
3330 case Hash("sqshl_z_p_zz"):
3331 VIXL_UNIMPLEMENTED();
3332 break;
3333 case Hash("sqshlr_z_p_zz"):
3334 VIXL_UNIMPLEMENTED();
3335 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003336 case Hash("srshl_z_p_zz"):
3337 VIXL_UNIMPLEMENTED();
3338 break;
3339 case Hash("srshlr_z_p_zz"):
3340 VIXL_UNIMPLEMENTED();
3341 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003342 case Hash("uqrshl_z_p_zz"):
3343 VIXL_UNIMPLEMENTED();
3344 break;
3345 case Hash("uqrshlr_z_p_zz"):
3346 VIXL_UNIMPLEMENTED();
3347 break;
3348 case Hash("uqshl_z_p_zz"):
3349 VIXL_UNIMPLEMENTED();
3350 break;
3351 case Hash("uqshlr_z_p_zz"):
3352 VIXL_UNIMPLEMENTED();
3353 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003354 case Hash("urshl_z_p_zz"):
3355 VIXL_UNIMPLEMENTED();
3356 break;
3357 case Hash("urshlr_z_p_zz"):
3358 VIXL_UNIMPLEMENTED();
3359 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003360 default:
3361 VIXL_UNIMPLEMENTED();
3362 }
3363}
3364
3365void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3366 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003367 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003368
3369 std::pair<int, int> shift_and_lane_size =
3370 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3371 unsigned lane_size = shift_and_lane_size.second;
3372 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3373 int right_shift_dist = shift_and_lane_size.first;
3374 int left_shift_dist = (8 << lane_size) - right_shift_dist;
3375 SimVRegister result;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003376
3377 switch (form_hash_) {
3378 case Hash("sqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003379 sqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003380 break;
3381 case Hash("sqshlu_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003382 sqshlu(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003383 break;
3384 case Hash("srshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003385 sshr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003386 break;
3387 case Hash("uqshl_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003388 uqshl(vform, result, zdn, left_shift_dist);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003389 break;
3390 case Hash("urshr_z_p_zi"):
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003391 ushr(vform, result, zdn, right_shift_dist).Round(vform);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003392 break;
3393 default:
3394 VIXL_UNIMPLEMENTED();
3395 }
Martyn Capewelld8fc5432020-09-09 18:03:09 +01003396 mov_merging(vform, zdn, pg, result);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003397}
3398
Martyn Capewell97ca8062020-10-23 14:45:14 +01003399void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3400 VIXL_ASSERT(form_hash_ == Hash("xar_z_zzi"));
3401
3402 SimVRegister& zdn = ReadVRegister(instr->GetRd());
3403 SimVRegister& zm = ReadVRegister(instr->GetRn());
3404
3405 std::pair<int, int> shift_and_lane_size =
3406 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3407 unsigned lane_size = shift_and_lane_size.second;
3408 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3409 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3410 int shift_dist = shift_and_lane_size.first;
Martyn Capewellb1b95782020-10-23 15:59:49 +01003411 eor(vform, zdn, zdn, zm);
Martyn Capewell97ca8062020-10-23 14:45:14 +01003412 ror(vform, zdn, zdn, shift_dist);
3413}
3414
Martyn Capewell6bf28752020-08-05 11:57:06 +01003415void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
Martyn Capewell819dcf92020-10-20 16:07:09 +01003416 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell6bf28752020-08-05 11:57:06 +01003417 SimVRegister& zdn = ReadVRegister(instr->GetRd());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003418 SimVRegister& zm = ReadVRegister(instr->GetRn());
Martyn Capewell819dcf92020-10-20 16:07:09 +01003419 int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003420
3421 switch (form_hash_) {
3422 case Hash("cadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003423 cadd(vform, zdn, zdn, zm, rot);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003424 break;
3425 case Hash("sqcadd_z_zz"):
Martyn Capewell819dcf92020-10-20 16:07:09 +01003426 cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003427 break;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003428 default:
3429 VIXL_UNIMPLEMENTED();
3430 }
3431}
3432
3433void Simulator::Simulate_ZtD_PgZ_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 Capewell932cbb02020-11-10 16:53:31 +00003436 uint64_t xm = ReadXRegister(instr->GetRm());
3437
3438 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3439 int msize = -1;
3440 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003441
3442 switch (form_hash_) {
3443 case Hash("ldnt1b_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003444 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003445 break;
3446 case Hash("ldnt1d_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003447 msize = 3;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003448 break;
3449 case Hash("ldnt1h_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003450 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003451 break;
3452 case Hash("ldnt1sb_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003453 msize = 0;
3454 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003455 break;
3456 case Hash("ldnt1sh_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003457 msize = 1;
3458 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003459 break;
3460 case Hash("ldnt1sw_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003461 msize = 2;
3462 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003463 break;
3464 case Hash("ldnt1w_z_p_ar_d_64_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003465 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003466 break;
3467 default:
3468 VIXL_UNIMPLEMENTED();
3469 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003470 addr.SetMsizeInBytesLog2(msize);
3471 SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003472}
3473
3474void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3475 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003476 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003477 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003478
Martyn Capewell1ac83572020-11-11 16:15:58 +00003479 LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3480 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_d_64_unscaled")) ||
3481 (form_hash_ == Hash("stnt1d_z_p_ar_d_64_unscaled")) ||
3482 (form_hash_ == Hash("stnt1h_z_p_ar_d_64_unscaled")) ||
3483 (form_hash_ == Hash("stnt1w_z_p_ar_d_64_unscaled")));
3484
3485 addr.SetMsizeInBytesLog2(
3486 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3487 SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003488}
3489
3490void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3491 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003492 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell932cbb02020-11-10 16:53:31 +00003493 uint64_t xm = ReadXRegister(instr->GetRm());
3494
3495 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3496 int msize = -1;
3497 bool is_signed = false;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003498
3499 switch (form_hash_) {
3500 case Hash("ldnt1b_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003501 msize = 0;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003502 break;
3503 case Hash("ldnt1h_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003504 msize = 1;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003505 break;
3506 case Hash("ldnt1sb_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003507 msize = 0;
3508 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003509 break;
3510 case Hash("ldnt1sh_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003511 msize = 1;
3512 is_signed = true;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003513 break;
3514 case Hash("ldnt1w_z_p_ar_s_x32_unscaled"):
Martyn Capewell932cbb02020-11-10 16:53:31 +00003515 msize = 2;
Martyn Capewell6bf28752020-08-05 11:57:06 +01003516 break;
3517 default:
3518 VIXL_UNIMPLEMENTED();
3519 }
Martyn Capewell932cbb02020-11-10 16:53:31 +00003520 addr.SetMsizeInBytesLog2(msize);
3521 SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003522}
3523
3524void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3525 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003526 SimVRegister& zn = ReadVRegister(instr->GetRn());
Martyn Capewell1ac83572020-11-11 16:15:58 +00003527 uint64_t xm = ReadXRegister(instr->GetRm());
Martyn Capewell6bf28752020-08-05 11:57:06 +01003528
Martyn Capewell1ac83572020-11-11 16:15:58 +00003529 LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3530 VIXL_ASSERT((form_hash_ == Hash("stnt1b_z_p_ar_s_x32_unscaled")) ||
3531 (form_hash_ == Hash("stnt1h_z_p_ar_s_x32_unscaled")) ||
3532 (form_hash_ == Hash("stnt1w_z_p_ar_s_x32_unscaled")));
3533
3534 addr.SetMsizeInBytesLog2(
3535 instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3536 SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
Martyn Capewell6bf28752020-08-05 11:57:06 +01003537}
3538
Jacob Bramley18c97bd2019-01-18 16:01:08 +00003539void Simulator::VisitReserved(const Instruction* instr) {
3540 // UDF is the only instruction in this group, and the Decoder is precise here.
3541 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3542
3543 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3544 reinterpret_cast<const void*>(instr),
3545 instr->GetInstructionBits());
3546 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3547}
3548
3549
Alexandre Ramesd3832962016-07-04 15:03:43 +01003550void Simulator::VisitUnimplemented(const Instruction* instr) {
3551 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3552 reinterpret_cast<const void*>(instr),
3553 instr->GetInstructionBits());
3554 VIXL_UNIMPLEMENTED();
3555}
3556
3557
3558void Simulator::VisitUnallocated(const Instruction* instr) {
3559 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3560 reinterpret_cast<const void*>(instr),
3561 instr->GetInstructionBits());
3562 VIXL_UNIMPLEMENTED();
3563}
3564
3565
3566void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3567 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3568 (instr->Mask(PCRelAddressingMask) == ADRP));
3569
3570 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3571}
3572
3573
3574void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3575 switch (instr->Mask(UnconditionalBranchMask)) {
3576 case BL:
3577 WriteLr(instr->GetNextInstruction());
3578 VIXL_FALLTHROUGH();
3579 case B:
3580 WritePc(instr->GetImmPCOffsetTarget());
3581 break;
3582 default:
3583 VIXL_UNREACHABLE();
3584 }
3585}
3586
3587
3588void Simulator::VisitConditionalBranch(const Instruction* instr) {
3589 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3590 if (ConditionPassed(instr->GetConditionBranch())) {
3591 WritePc(instr->GetImmPCOffsetTarget());
3592 }
3593}
3594
Martyn Capewellcb963f72018-10-22 15:25:28 +01003595BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3596 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3597 case BLR:
3598 case BLRAA:
3599 case BLRAB:
3600 case BLRAAZ:
3601 case BLRABZ:
3602 return BranchAndLink;
3603 case BR:
3604 case BRAA:
3605 case BRAB:
3606 case BRAAZ:
3607 case BRABZ:
3608 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3609 !PcIsInGuardedPage()) {
3610 return BranchFromUnguardedOrToIP;
3611 }
3612 return BranchFromGuardedNotToIP;
3613 }
3614 return DefaultBType;
3615}
Alexandre Ramesd3832962016-07-04 15:03:43 +01003616
3617void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003618 bool authenticate = false;
3619 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01003620 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01003621 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003622
3623 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3624 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01003625 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003626 VIXL_FALLTHROUGH();
3627 case BR:
3628 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01003629 break;
3630
3631 case BLRAAZ:
3632 case BLRABZ:
3633 link = true;
3634 VIXL_FALLTHROUGH();
3635 case BRAAZ:
3636 case BRABZ:
3637 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003638 break;
3639
3640 case BLRAA:
3641 case BLRAB:
3642 link = true;
3643 VIXL_FALLTHROUGH();
3644 case BRAA:
3645 case BRAB:
3646 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01003647 context = ReadXRegister(instr->GetRd());
3648 break;
3649
3650 case RETAA:
3651 case RETAB:
3652 authenticate = true;
3653 addr = ReadXRegister(kLinkRegCode);
3654 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003655 break;
3656 default:
3657 VIXL_UNREACHABLE();
3658 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003659
3660 if (link) {
3661 WriteLr(instr->GetNextInstruction());
3662 }
3663
3664 if (authenticate) {
3665 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3666 addr = AuthPAC(addr, context, key, kInstructionPointer);
3667
3668 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3669 if (((addr >> error_lsb) & 0x3) != 0x0) {
3670 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3671 }
3672 }
3673
Martyn Capewellcb963f72018-10-22 15:25:28 +01003674 WritePc(Instruction::Cast(addr));
3675 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003676}
3677
3678
3679void Simulator::VisitTestBranch(const Instruction* instr) {
3680 unsigned bit_pos =
3681 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3682 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3683 bool take_branch = false;
3684 switch (instr->Mask(TestBranchMask)) {
3685 case TBZ:
3686 take_branch = bit_zero;
3687 break;
3688 case TBNZ:
3689 take_branch = !bit_zero;
3690 break;
3691 default:
3692 VIXL_UNIMPLEMENTED();
3693 }
3694 if (take_branch) {
3695 WritePc(instr->GetImmPCOffsetTarget());
3696 }
3697}
3698
3699
3700void Simulator::VisitCompareBranch(const Instruction* instr) {
3701 unsigned rt = instr->GetRt();
3702 bool take_branch = false;
3703 switch (instr->Mask(CompareBranchMask)) {
3704 case CBZ_w:
3705 take_branch = (ReadWRegister(rt) == 0);
3706 break;
3707 case CBZ_x:
3708 take_branch = (ReadXRegister(rt) == 0);
3709 break;
3710 case CBNZ_w:
3711 take_branch = (ReadWRegister(rt) != 0);
3712 break;
3713 case CBNZ_x:
3714 take_branch = (ReadXRegister(rt) != 0);
3715 break;
3716 default:
3717 VIXL_UNIMPLEMENTED();
3718 }
3719 if (take_branch) {
3720 WritePc(instr->GetImmPCOffsetTarget());
3721 }
3722}
3723
3724
3725void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3726 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3727 bool set_flags = instr->GetFlagsUpdate();
3728 int64_t new_val = 0;
3729 Instr operation = instr->Mask(AddSubOpMask);
3730
3731 switch (operation) {
3732 case ADD:
3733 case ADDS: {
3734 new_val = AddWithCarry(reg_size,
3735 set_flags,
3736 ReadRegister(reg_size,
3737 instr->GetRn(),
3738 instr->GetRnMode()),
3739 op2);
3740 break;
3741 }
3742 case SUB:
3743 case SUBS: {
3744 new_val = AddWithCarry(reg_size,
3745 set_flags,
3746 ReadRegister(reg_size,
3747 instr->GetRn(),
3748 instr->GetRnMode()),
3749 ~op2,
3750 1);
3751 break;
3752 }
3753 default:
3754 VIXL_UNREACHABLE();
3755 }
3756
3757 WriteRegister(reg_size,
3758 instr->GetRd(),
3759 new_val,
3760 LogRegWrites,
3761 instr->GetRdMode());
3762}
3763
3764
3765void Simulator::VisitAddSubShifted(const Instruction* instr) {
3766 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3767 int64_t op2 = ShiftOperand(reg_size,
3768 ReadRegister(reg_size, instr->GetRm()),
3769 static_cast<Shift>(instr->GetShiftDP()),
3770 instr->GetImmDPShift());
3771 AddSubHelper(instr, op2);
3772}
3773
3774
3775void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3776 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01003777 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003778 AddSubHelper(instr, op2);
3779}
3780
3781
3782void Simulator::VisitAddSubExtended(const Instruction* instr) {
3783 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3784 int64_t op2 = ExtendValue(reg_size,
3785 ReadRegister(reg_size, instr->GetRm()),
3786 static_cast<Extend>(instr->GetExtendMode()),
3787 instr->GetImmExtendShift());
3788 AddSubHelper(instr, op2);
3789}
3790
3791
3792void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3793 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3794 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3795 int64_t new_val;
3796
3797 if ((instr->Mask(AddSubOpMask) == SUB) ||
3798 (instr->Mask(AddSubOpMask) == SUBS)) {
3799 op2 = ~op2;
3800 }
3801
3802 new_val = AddWithCarry(reg_size,
3803 instr->GetFlagsUpdate(),
3804 ReadRegister(reg_size, instr->GetRn()),
3805 op2,
3806 ReadC());
3807
3808 WriteRegister(reg_size, instr->GetRd(), new_val);
3809}
3810
3811
Alexander Gilday2487f142018-11-05 13:07:27 +00003812void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3813 switch (instr->Mask(RotateRightIntoFlagsMask)) {
3814 case RMIF: {
3815 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3816 unsigned shift = instr->GetImmRMIFRotation();
3817 unsigned mask = instr->GetNzcv();
3818 uint64_t rotated = RotateRight(value, shift, kXRegSize);
3819
3820 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3821 break;
3822 }
3823 }
3824}
3825
3826
3827void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3828 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3829 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3830
3831 unsigned sign_bit = (value >> msb) & 1;
3832 unsigned overflow_bit = (value >> (msb + 1)) & 1;
3833 ReadNzcv().SetN(sign_bit);
3834 ReadNzcv().SetZ((value << (31 - msb)) == 0);
3835 ReadNzcv().SetV(sign_bit ^ overflow_bit);
3836}
3837
3838
Alexandre Ramesd3832962016-07-04 15:03:43 +01003839void Simulator::VisitLogicalShifted(const Instruction* instr) {
3840 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3841 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3842 unsigned shift_amount = instr->GetImmDPShift();
3843 int64_t op2 = ShiftOperand(reg_size,
3844 ReadRegister(reg_size, instr->GetRm()),
3845 shift_type,
3846 shift_amount);
3847 if (instr->Mask(NOT) == NOT) {
3848 op2 = ~op2;
3849 }
3850 LogicalHelper(instr, op2);
3851}
3852
3853
3854void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3855 LogicalHelper(instr, instr->GetImmLogical());
3856}
3857
3858
3859void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3860 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3861 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3862 int64_t result = 0;
3863 bool update_flags = false;
3864
3865 // Switch on the logical operation, stripping out the NOT bit, as it has a
3866 // different meaning for logical immediate instructions.
3867 switch (instr->Mask(LogicalOpMask & ~NOT)) {
3868 case ANDS:
3869 update_flags = true;
3870 VIXL_FALLTHROUGH();
3871 case AND:
3872 result = op1 & op2;
3873 break;
3874 case ORR:
3875 result = op1 | op2;
3876 break;
3877 case EOR:
3878 result = op1 ^ op2;
3879 break;
3880 default:
3881 VIXL_UNIMPLEMENTED();
3882 }
3883
3884 if (update_flags) {
3885 ReadNzcv().SetN(CalcNFlag(result, reg_size));
3886 ReadNzcv().SetZ(CalcZFlag(result));
3887 ReadNzcv().SetC(0);
3888 ReadNzcv().SetV(0);
3889 LogSystemRegister(NZCV);
3890 }
3891
3892 WriteRegister(reg_size,
3893 instr->GetRd(),
3894 result,
3895 LogRegWrites,
3896 instr->GetRdMode());
3897}
3898
3899
3900void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3901 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3902 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3903}
3904
3905
3906void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3907 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3908}
3909
3910
3911void Simulator::ConditionalCompareHelper(const Instruction* instr,
3912 int64_t op2) {
3913 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3914 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3915
3916 if (ConditionPassed(instr->GetCondition())) {
3917 // If the condition passes, set the status flags to the result of comparing
3918 // the operands.
3919 if (instr->Mask(ConditionalCompareMask) == CCMP) {
3920 AddWithCarry(reg_size, true, op1, ~op2, 1);
3921 } else {
3922 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3923 AddWithCarry(reg_size, true, op1, op2, 0);
3924 }
3925 } else {
3926 // If the condition fails, set the status flags to the nzcv immediate.
3927 ReadNzcv().SetFlags(instr->GetNzcv());
3928 LogSystemRegister(NZCV);
3929 }
3930}
3931
3932
3933void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3934 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3935 LoadStoreHelper(instr, offset, Offset);
3936}
3937
3938
3939void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3940 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3941}
3942
3943
3944void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3945 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3946}
3947
3948
3949void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3950 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3951}
3952
3953
Alexander Gilday311edf22018-10-29 13:41:41 +00003954template <typename T1, typename T2>
3955void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
3956 unsigned rt = instr->GetRt();
3957 unsigned rn = instr->GetRn();
3958
3959 unsigned element_size = sizeof(T2);
3960 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3961 int offset = instr->GetImmLS();
3962 address += offset;
3963
3964 // Verify that the address is available to the host.
3965 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3966
3967 // Check the alignment of `address`.
3968 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3969 VIXL_ALIGNMENT_EXCEPTION();
3970 }
3971
3972 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
3973
3974 // Approximate load-acquire by issuing a full barrier after the load.
3975 __sync_synchronize();
3976
Jacob Bramley423e5422019-11-13 19:15:55 +00003977 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00003978}
3979
3980
3981template <typename T>
3982void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
3983 unsigned rt = instr->GetRt();
3984 unsigned rn = instr->GetRn();
3985
3986 unsigned element_size = sizeof(T);
3987 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3988 int offset = instr->GetImmLS();
3989 address += offset;
3990
3991 // Verify that the address is available to the host.
3992 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3993
3994 // Check the alignment of `address`.
3995 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3996 VIXL_ALIGNMENT_EXCEPTION();
3997 }
3998
3999 // Approximate store-release by issuing a full barrier after the load.
4000 __sync_synchronize();
4001
4002 Memory::Write<T>(address, ReadRegister<T>(rt));
4003
Jacob Bramley423e5422019-11-13 19:15:55 +00004004 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00004005}
4006
4007
4008void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
4009 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
4010 case LDAPURB:
4011 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
4012 break;
4013 case LDAPURH:
4014 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
4015 break;
4016 case LDAPUR_w:
4017 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
4018 break;
4019 case LDAPUR_x:
4020 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
4021 break;
4022 case LDAPURSB_w:
4023 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
4024 break;
4025 case LDAPURSB_x:
4026 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
4027 break;
4028 case LDAPURSH_w:
4029 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
4030 break;
4031 case LDAPURSH_x:
4032 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
4033 break;
4034 case LDAPURSW:
4035 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
4036 break;
4037 case STLURB:
4038 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
4039 break;
4040 case STLURH:
4041 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4042 break;
4043 case STLUR_w:
4044 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4045 break;
4046 case STLUR_x:
4047 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4048 break;
4049 }
4050}
4051
4052
Alexander Gilday75605592018-11-01 09:30:29 +00004053void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4054 unsigned dst = instr->GetRt();
4055 unsigned addr_reg = instr->GetRn();
4056
4057 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4058
4059 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4060 address = AuthPAC(address, 0, key, kDataPointer);
4061
4062 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4063 if (((address >> error_lsb) & 0x3) != 0x0) {
4064 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4065 }
4066
4067
4068 if ((addr_reg == 31) && ((address % 16) != 0)) {
4069 // When the base register is SP the stack pointer is required to be
4070 // quadword aligned prior to the address calculation and write-backs.
4071 // Misalignment will cause a stack alignment fault.
4072 VIXL_ALIGNMENT_EXCEPTION();
4073 }
4074
4075 int64_t offset = instr->GetImmLSPAC();
4076 address += offset;
4077
4078 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4079 // Pre-index mode.
4080 VIXL_ASSERT(offset != 0);
4081 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4082 }
4083
4084 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4085
4086 // Verify that the calculated address is available to the host.
4087 VIXL_ASSERT(address == addr_ptr);
4088
4089 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
4090 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00004091 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00004092}
4093
4094
Alexandre Ramesd3832962016-07-04 15:03:43 +01004095void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4096 Extend ext = static_cast<Extend>(instr->GetExtendMode());
4097 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4098 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4099
4100 int64_t offset =
4101 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4102 LoadStoreHelper(instr, offset, Offset);
4103}
4104
4105
4106void Simulator::LoadStoreHelper(const Instruction* instr,
4107 int64_t offset,
4108 AddrMode addrmode) {
4109 unsigned srcdst = instr->GetRt();
4110 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4111
Jacob Bramley423e5422019-11-13 19:15:55 +00004112 bool rt_is_vreg = false;
4113 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004114 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4115 switch (op) {
4116 case LDRB_w:
4117 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004118 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004119 break;
4120 case LDRH_w:
4121 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004122 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004123 break;
4124 case LDR_w:
4125 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004126 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004127 break;
4128 case LDR_x:
4129 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004130 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004131 break;
4132 case LDRSB_w:
4133 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004134 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004135 break;
4136 case LDRSH_w:
4137 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004138 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004139 break;
4140 case LDRSB_x:
4141 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004142 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004143 break;
4144 case LDRSH_x:
4145 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004146 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004147 break;
4148 case LDRSW_x:
4149 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004150 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004151 break;
4152 case LDR_b:
4153 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004154 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004155 break;
4156 case LDR_h:
4157 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004158 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004159 break;
4160 case LDR_s:
4161 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004162 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004163 break;
4164 case LDR_d:
4165 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004166 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004167 break;
4168 case LDR_q:
4169 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004170 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004171 break;
4172
4173 case STRB_w:
4174 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
4175 break;
4176 case STRH_w:
4177 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
4178 break;
4179 case STR_w:
4180 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
4181 break;
4182 case STR_x:
4183 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
4184 break;
4185 case STR_b:
4186 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004187 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004188 break;
4189 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01004190 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004191 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004192 break;
4193 case STR_s:
4194 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004195 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004196 break;
4197 case STR_d:
4198 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004199 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004200 break;
4201 case STR_q:
4202 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00004203 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004204 break;
4205
4206 // Ignore prfm hint instructions.
4207 case PRFM:
4208 break;
4209
4210 default:
4211 VIXL_UNIMPLEMENTED();
4212 }
4213
Jacob Bramley423e5422019-11-13 19:15:55 +00004214 // Print a detailed trace (including the memory address).
4215 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004216 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00004217 unsigned result_size = extend ? extend_to_size : access_size;
4218 PrintRegisterFormat print_format =
4219 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4220 : GetPrintRegisterFormatForSize(result_size);
4221
Alexandre Ramesd3832962016-07-04 15:03:43 +01004222 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004223 if (rt_is_vreg) {
4224 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004225 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004226 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004227 }
4228 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004229 if (rt_is_vreg) {
4230 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004231 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004232 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004233 }
4234 } else {
4235 VIXL_ASSERT(op == PRFM);
4236 }
4237
4238 local_monitor_.MaybeClear();
4239}
4240
4241
4242void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4243 LoadStorePairHelper(instr, Offset);
4244}
4245
4246
4247void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4248 LoadStorePairHelper(instr, PreIndex);
4249}
4250
4251
4252void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4253 LoadStorePairHelper(instr, PostIndex);
4254}
4255
4256
4257void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4258 LoadStorePairHelper(instr, Offset);
4259}
4260
4261
4262void Simulator::LoadStorePairHelper(const Instruction* instr,
4263 AddrMode addrmode) {
4264 unsigned rt = instr->GetRt();
4265 unsigned rt2 = instr->GetRt2();
4266 int element_size = 1 << instr->GetSizeLSPair();
4267 int64_t offset = instr->GetImmLSPair() * element_size;
4268 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4269 uintptr_t address2 = address + element_size;
4270
4271 LoadStorePairOp op =
4272 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4273
4274 // 'rt' and 'rt2' can only be aliased for stores.
4275 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4276
Jacob Bramley423e5422019-11-13 19:15:55 +00004277 bool rt_is_vreg = false;
4278 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004279 switch (op) {
4280 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4281 // will print a more detailed log.
4282 case LDP_w: {
4283 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4284 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
4285 break;
4286 }
4287 case LDP_s: {
4288 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
4289 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004290 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004291 break;
4292 }
4293 case LDP_x: {
4294 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4295 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
4296 break;
4297 }
4298 case LDP_d: {
4299 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
4300 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004301 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004302 break;
4303 }
4304 case LDP_q: {
4305 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
4306 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004307 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004308 break;
4309 }
4310 case LDPSW_x: {
4311 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
4312 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004313 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004314 break;
4315 }
4316 case STP_w: {
4317 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4318 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
4319 break;
4320 }
4321 case STP_s: {
4322 Memory::Write<float>(address, ReadSRegister(rt));
4323 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004324 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004325 break;
4326 }
4327 case STP_x: {
4328 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4329 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
4330 break;
4331 }
4332 case STP_d: {
4333 Memory::Write<double>(address, ReadDRegister(rt));
4334 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004335 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004336 break;
4337 }
4338 case STP_q: {
4339 Memory::Write<qreg_t>(address, ReadQRegister(rt));
4340 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00004341 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004342 break;
4343 }
4344 default:
4345 VIXL_UNREACHABLE();
4346 }
4347
Jacob Bramley423e5422019-11-13 19:15:55 +00004348 // Print a detailed trace (including the memory address).
4349 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4350 PrintRegisterFormat print_format =
4351 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4352 : GetPrintRegisterFormatForSize(result_size);
4353
Alexandre Ramesd3832962016-07-04 15:03:43 +01004354 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004355 if (rt_is_vreg) {
4356 LogVRead(rt, print_format, address);
4357 LogVRead(rt2, print_format, address2);
4358 } else if (sign_extend) {
4359 LogExtendingRead(rt, print_format, element_size, address);
4360 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004361 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004362 LogRead(rt, print_format, address);
4363 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004364 }
4365 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004366 if (rt_is_vreg) {
4367 LogVWrite(rt, print_format, address);
4368 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004369 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00004370 LogWrite(rt, print_format, address);
4371 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004372 }
4373 }
4374
4375 local_monitor_.MaybeClear();
4376}
4377
4378
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004379template <typename T>
4380void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4381 unsigned rs = instr->GetRs();
4382 unsigned rt = instr->GetRt();
4383 unsigned rn = instr->GetRn();
4384
4385 unsigned element_size = sizeof(T);
4386 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4387
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004388 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4389
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004390 bool is_acquire = instr->ExtractBit(22) == 1;
4391 bool is_release = instr->ExtractBit(15) == 1;
4392
4393 T comparevalue = ReadRegister<T>(rs);
4394 T newvalue = ReadRegister<T>(rt);
4395
4396 // The architecture permits that the data read clears any exclusive monitors
4397 // associated with that location, even if the compare subsequently fails.
4398 local_monitor_.Clear();
4399
4400 T data = Memory::Read<T>(address);
4401 if (is_acquire) {
4402 // Approximate load-acquire by issuing a full barrier after the load.
4403 __sync_synchronize();
4404 }
4405
4406 if (data == comparevalue) {
4407 if (is_release) {
4408 // Approximate store-release by issuing a full barrier before the store.
4409 __sync_synchronize();
4410 }
4411 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00004412 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004413 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004414 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004415 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004416}
4417
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004418
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004419template <typename T>
4420void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4421 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4422 unsigned rs = instr->GetRs();
4423 unsigned rt = instr->GetRt();
4424 unsigned rn = instr->GetRn();
4425
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004426 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004427
4428 unsigned element_size = sizeof(T);
4429 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004430
4431 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4432
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004433 uint64_t address2 = address + element_size;
4434
4435 bool is_acquire = instr->ExtractBit(22) == 1;
4436 bool is_release = instr->ExtractBit(15) == 1;
4437
4438 T comparevalue_high = ReadRegister<T>(rs + 1);
4439 T comparevalue_low = ReadRegister<T>(rs);
4440 T newvalue_high = ReadRegister<T>(rt + 1);
4441 T newvalue_low = ReadRegister<T>(rt);
4442
4443 // The architecture permits that the data read clears any exclusive monitors
4444 // associated with that location, even if the compare subsequently fails.
4445 local_monitor_.Clear();
4446
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004447 T data_low = Memory::Read<T>(address);
4448 T data_high = Memory::Read<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004449
4450 if (is_acquire) {
4451 // Approximate load-acquire by issuing a full barrier after the load.
4452 __sync_synchronize();
4453 }
4454
4455 bool same =
4456 (data_high == comparevalue_high) && (data_low == comparevalue_low);
4457 if (same) {
4458 if (is_release) {
4459 // Approximate store-release by issuing a full barrier before the store.
4460 __sync_synchronize();
4461 }
4462
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004463 Memory::Write<T>(address, newvalue_low);
4464 Memory::Write<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004465 }
4466
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004467 WriteRegister<T>(rs + 1, data_high, NoRegLog);
4468 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004469
Jacob Bramley423e5422019-11-13 19:15:55 +00004470 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004471 LogRead(rs, format, address);
4472 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004473
4474 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01004475 LogWrite(rt, format, address);
4476 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004477 }
4478}
4479
Jacob Bramley85a9c102019-12-09 17:48:29 +00004480bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4481 // To simulate fault-tolerant loads, we need to know what host addresses we
4482 // can access without generating a real fault. One way to do that is to
4483 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
4484 // and less intrusive than using (global) signal handlers.
4485 //
4486 // [1]: https://stackoverflow.com/questions/7134590
4487
4488 size_t written = 0;
4489 bool can_read = true;
4490 // `write` will normally return after one invocation, but it is allowed to
4491 // handle only part of the operation, so wrap it in a loop.
4492 while (can_read && (written < size)) {
4493 ssize_t result = write(dummy_pipe_fd_[1],
4494 reinterpret_cast<void*>(address + written),
4495 size - written);
4496 if (result > 0) {
4497 written += result;
4498 } else {
4499 switch (result) {
4500 case -EPERM:
4501 case -EFAULT:
4502 // The address range is not accessible.
4503 // `write` is supposed to return -EFAULT in this case, but in practice
4504 // it seems to return -EPERM, so we accept that too.
4505 can_read = false;
4506 break;
4507 case -EINTR:
4508 // The call was interrupted by a signal. Just try again.
4509 break;
4510 default:
4511 // Any other error is fatal.
4512 VIXL_ABORT();
4513 }
4514 }
4515 }
4516 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4517 // the dummy data is buffered. As before, we expect to drain the whole write
4518 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
4519 // function is primarily intended to implement SVE fault-tolerant loads, so
4520 // the maximum Z register size is a good default buffer size.
4521 char buffer[kZRegMaxSizeInBytes];
4522 while (written > 0) {
4523 ssize_t result = read(dummy_pipe_fd_[0],
4524 reinterpret_cast<void*>(buffer),
4525 sizeof(buffer));
4526 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4527 // we've read everything that was written, so treat 0 as an error.
4528 if (result > 0) {
4529 VIXL_ASSERT(static_cast<size_t>(result) <= written);
4530 written -= result;
4531 } else {
4532 // For -EINTR, just try again. We can't handle any other error.
4533 VIXL_CHECK(result == -EINTR);
4534 }
4535 }
4536
4537 return can_read;
4538}
Alexandre Ramesd3832962016-07-04 15:03:43 +01004539
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004540void Simulator::PrintExclusiveAccessWarning() {
4541 if (print_exclusive_access_warning_) {
4542 fprintf(stderr,
4543 "%sWARNING:%s VIXL simulator support for "
4544 "load-/store-/clear-exclusive "
4545 "instructions is limited. Refer to the README for details.%s\n",
4546 clr_warning,
4547 clr_warning_message,
4548 clr_normal);
4549 print_exclusive_access_warning_ = false;
4550 }
4551}
4552
Alexandre Ramesd3832962016-07-04 15:03:43 +01004553void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004554 LoadStoreExclusive op =
4555 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4556
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004557 switch (op) {
4558 case CAS_w:
4559 case CASA_w:
4560 case CASL_w:
4561 case CASAL_w:
4562 CompareAndSwapHelper<uint32_t>(instr);
4563 break;
4564 case CAS_x:
4565 case CASA_x:
4566 case CASL_x:
4567 case CASAL_x:
4568 CompareAndSwapHelper<uint64_t>(instr);
4569 break;
4570 case CASB:
4571 case CASAB:
4572 case CASLB:
4573 case CASALB:
4574 CompareAndSwapHelper<uint8_t>(instr);
4575 break;
4576 case CASH:
4577 case CASAH:
4578 case CASLH:
4579 case CASALH:
4580 CompareAndSwapHelper<uint16_t>(instr);
4581 break;
4582 case CASP_w:
4583 case CASPA_w:
4584 case CASPL_w:
4585 case CASPAL_w:
4586 CompareAndSwapPairHelper<uint32_t>(instr);
4587 break;
4588 case CASP_x:
4589 case CASPA_x:
4590 case CASPL_x:
4591 case CASPAL_x:
4592 CompareAndSwapPairHelper<uint64_t>(instr);
4593 break;
4594 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004595 PrintExclusiveAccessWarning();
4596
4597 unsigned rs = instr->GetRs();
4598 unsigned rt = instr->GetRt();
4599 unsigned rt2 = instr->GetRt2();
4600 unsigned rn = instr->GetRn();
4601
4602 bool is_exclusive = !instr->GetLdStXNotExclusive();
4603 bool is_acquire_release =
4604 !is_exclusive || instr->GetLdStXAcquireRelease();
4605 bool is_load = instr->GetLdStXLoad();
4606 bool is_pair = instr->GetLdStXPair();
4607
4608 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4609 unsigned access_size = is_pair ? element_size * 2 : element_size;
4610 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4611
4612 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4613
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004614 if (is_load) {
4615 if (is_exclusive) {
4616 local_monitor_.MarkExclusive(address, access_size);
4617 } else {
4618 // Any non-exclusive load can clear the local monitor as a side
4619 // effect. We don't need to do this, but it is useful to stress the
4620 // simulated code.
4621 local_monitor_.Clear();
4622 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004623
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004624 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4625 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00004626 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004627 switch (op) {
4628 case LDXRB_w:
4629 case LDAXRB_w:
4630 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004631 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004632 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004633 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004634 break;
4635 case LDXRH_w:
4636 case LDAXRH_w:
4637 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004638 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004639 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004640 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004641 break;
4642 case LDXR_w:
4643 case LDAXR_w:
4644 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004645 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004646 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004647 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004648 break;
4649 case LDXR_x:
4650 case LDAXR_x:
4651 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004652 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004653 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004654 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004655 break;
4656 case LDXP_w:
4657 case LDAXP_w:
4658 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
4659 WriteWRegister(rt2,
4660 Memory::Read<uint32_t>(address + element_size),
4661 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004662 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004663 break;
4664 case LDXP_x:
4665 case LDAXP_x:
4666 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
4667 WriteXRegister(rt2,
4668 Memory::Read<uint64_t>(address + element_size),
4669 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004670 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004671 break;
4672 default:
4673 VIXL_UNREACHABLE();
4674 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004675
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004676 if (is_acquire_release) {
4677 // Approximate load-acquire by issuing a full barrier after the load.
4678 __sync_synchronize();
4679 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004680
Jacob Bramley423e5422019-11-13 19:15:55 +00004681 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4682 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004683 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004684 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004685 }
4686 } else {
4687 if (is_acquire_release) {
4688 // Approximate store-release by issuing a full barrier before the
4689 // store.
4690 __sync_synchronize();
4691 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004692
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004693 bool do_store = true;
4694 if (is_exclusive) {
4695 do_store = local_monitor_.IsExclusive(address, access_size) &&
4696 global_monitor_.IsExclusive(address, access_size);
4697 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004698
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004699 // - All exclusive stores explicitly clear the local monitor.
4700 local_monitor_.Clear();
4701 } else {
4702 // - Any other store can clear the local monitor as a side effect.
4703 local_monitor_.MaybeClear();
4704 }
4705
4706 if (do_store) {
4707 switch (op) {
4708 case STXRB_w:
4709 case STLXRB_w:
4710 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004711 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004712 Memory::Write<uint8_t>(address, ReadWRegister(rt));
4713 break;
4714 case STXRH_w:
4715 case STLXRH_w:
4716 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004717 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004718 Memory::Write<uint16_t>(address, ReadWRegister(rt));
4719 break;
4720 case STXR_w:
4721 case STLXR_w:
4722 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004723 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004724 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4725 break;
4726 case STXR_x:
4727 case STLXR_x:
4728 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01004729 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004730 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4731 break;
4732 case STXP_w:
4733 case STLXP_w:
4734 Memory::Write<uint32_t>(address, ReadWRegister(rt));
4735 Memory::Write<uint32_t>(address + element_size,
4736 ReadWRegister(rt2));
4737 break;
4738 case STXP_x:
4739 case STLXP_x:
4740 Memory::Write<uint64_t>(address, ReadXRegister(rt));
4741 Memory::Write<uint64_t>(address + element_size,
4742 ReadXRegister(rt2));
4743 break;
4744 default:
4745 VIXL_UNREACHABLE();
4746 }
4747
Jacob Bramley423e5422019-11-13 19:15:55 +00004748 PrintRegisterFormat format =
4749 GetPrintRegisterFormatForSize(element_size);
4750 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004751 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00004752 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01004753 }
4754 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004755 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004756 }
4757}
4758
Jacob Bramleyca789742018-09-13 14:25:46 +01004759template <typename T>
4760void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4761 unsigned rs = instr->GetRs();
4762 unsigned rt = instr->GetRt();
4763 unsigned rn = instr->GetRn();
4764
4765 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4766 bool is_release = instr->ExtractBit(22) == 1;
4767
4768 unsigned element_size = sizeof(T);
4769 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4770
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004771 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004772
4773 T value = ReadRegister<T>(rs);
4774
4775 T data = Memory::Read<T>(address);
4776
4777 if (is_acquire) {
4778 // Approximate load-acquire by issuing a full barrier after the load.
4779 __sync_synchronize();
4780 }
4781
4782 T result = 0;
4783 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4784 case LDADDOp:
4785 result = data + value;
4786 break;
4787 case LDCLROp:
4788 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4789 result = data & ~value;
4790 break;
4791 case LDEOROp:
4792 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4793 result = data ^ value;
4794 break;
4795 case LDSETOp:
4796 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4797 result = data | value;
4798 break;
4799
4800 // Signed/Unsigned difference is done via the templated type T.
4801 case LDSMAXOp:
4802 case LDUMAXOp:
4803 result = (data > value) ? data : value;
4804 break;
4805 case LDSMINOp:
4806 case LDUMINOp:
4807 result = (data > value) ? value : data;
4808 break;
4809 }
4810
4811 if (is_release) {
4812 // Approximate store-release by issuing a full barrier before the store.
4813 __sync_synchronize();
4814 }
4815
4816 Memory::Write<T>(address, result);
4817 WriteRegister<T>(rt, data, NoRegLog);
4818
Jacob Bramley423e5422019-11-13 19:15:55 +00004819 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4820 LogRead(rt, format, address);
4821 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004822}
4823
4824template <typename T>
4825void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4826 unsigned rs = instr->GetRs();
4827 unsigned rt = instr->GetRt();
4828 unsigned rn = instr->GetRn();
4829
4830 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4831 bool is_release = instr->ExtractBit(22) == 1;
4832
4833 unsigned element_size = sizeof(T);
4834 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4835
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004836 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01004837
4838 T data = Memory::Read<T>(address);
4839 if (is_acquire) {
4840 // Approximate load-acquire by issuing a full barrier after the load.
4841 __sync_synchronize();
4842 }
4843
4844 if (is_release) {
4845 // Approximate store-release by issuing a full barrier before the store.
4846 __sync_synchronize();
4847 }
4848 Memory::Write<T>(address, ReadRegister<T>(rs));
4849
4850 WriteRegister<T>(rt, data);
4851
Jacob Bramley423e5422019-11-13 19:15:55 +00004852 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4853 LogRead(rt, format, address);
4854 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004855}
4856
4857template <typename T>
4858void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4859 unsigned rt = instr->GetRt();
4860 unsigned rn = instr->GetRn();
4861
4862 unsigned element_size = sizeof(T);
4863 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4864
Alexander Gilday3f89bf12018-10-25 14:03:49 +01004865 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4866
Jacob Bramleyca789742018-09-13 14:25:46 +01004867 WriteRegister<T>(rt, Memory::Read<T>(address));
4868
4869 // Approximate load-acquire by issuing a full barrier after the load.
4870 __sync_synchronize();
4871
Jacob Bramley423e5422019-11-13 19:15:55 +00004872 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01004873}
4874
4875#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4876 V(LDADD) \
4877 V(LDCLR) \
4878 V(LDEOR) \
4879 V(LDSET) \
4880 V(LDUMAX) \
4881 V(LDUMIN)
4882
4883#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4884 V(LDSMAX) \
4885 V(LDSMIN)
4886
4887void Simulator::VisitAtomicMemory(const Instruction* instr) {
4888 switch (instr->Mask(AtomicMemoryMask)) {
4889// clang-format off
4890#define SIM_FUNC_B(A) \
4891 case A##B: \
4892 case A##AB: \
4893 case A##LB: \
4894 case A##ALB:
4895#define SIM_FUNC_H(A) \
4896 case A##H: \
4897 case A##AH: \
4898 case A##LH: \
4899 case A##ALH:
4900#define SIM_FUNC_w(A) \
4901 case A##_w: \
4902 case A##A_w: \
4903 case A##L_w: \
4904 case A##AL_w:
4905#define SIM_FUNC_x(A) \
4906 case A##_x: \
4907 case A##A_x: \
4908 case A##L_x: \
4909 case A##AL_x:
4910
4911 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4912 AtomicMemorySimpleHelper<uint8_t>(instr);
4913 break;
4914 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4915 AtomicMemorySimpleHelper<int8_t>(instr);
4916 break;
4917 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4918 AtomicMemorySimpleHelper<uint16_t>(instr);
4919 break;
4920 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4921 AtomicMemorySimpleHelper<int16_t>(instr);
4922 break;
4923 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4924 AtomicMemorySimpleHelper<uint32_t>(instr);
4925 break;
4926 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4927 AtomicMemorySimpleHelper<int32_t>(instr);
4928 break;
4929 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4930 AtomicMemorySimpleHelper<uint64_t>(instr);
4931 break;
4932 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4933 AtomicMemorySimpleHelper<int64_t>(instr);
4934 break;
4935 // clang-format on
4936
4937 case SWPB:
4938 case SWPAB:
4939 case SWPLB:
4940 case SWPALB:
4941 AtomicMemorySwapHelper<uint8_t>(instr);
4942 break;
4943 case SWPH:
4944 case SWPAH:
4945 case SWPLH:
4946 case SWPALH:
4947 AtomicMemorySwapHelper<uint16_t>(instr);
4948 break;
4949 case SWP_w:
4950 case SWPA_w:
4951 case SWPL_w:
4952 case SWPAL_w:
4953 AtomicMemorySwapHelper<uint32_t>(instr);
4954 break;
4955 case SWP_x:
4956 case SWPA_x:
4957 case SWPL_x:
4958 case SWPAL_x:
4959 AtomicMemorySwapHelper<uint64_t>(instr);
4960 break;
4961 case LDAPRB:
4962 LoadAcquireRCpcHelper<uint8_t>(instr);
4963 break;
4964 case LDAPRH:
4965 LoadAcquireRCpcHelper<uint16_t>(instr);
4966 break;
4967 case LDAPR_w:
4968 LoadAcquireRCpcHelper<uint32_t>(instr);
4969 break;
4970 case LDAPR_x:
4971 LoadAcquireRCpcHelper<uint64_t>(instr);
4972 break;
4973 }
4974}
4975
Alexandre Ramesd3832962016-07-04 15:03:43 +01004976
4977void Simulator::VisitLoadLiteral(const Instruction* instr) {
4978 unsigned rt = instr->GetRt();
4979 uint64_t address = instr->GetLiteralAddress<uint64_t>();
4980
4981 // Verify that the calculated address is available to the host.
4982 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4983
4984 switch (instr->Mask(LoadLiteralMask)) {
4985 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
4986 // print a more detailed log.
4987 case LDR_w_lit:
4988 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004989 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004990 break;
4991 case LDR_x_lit:
4992 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004993 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004994 break;
4995 case LDR_s_lit:
4996 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00004997 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004998 break;
4999 case LDR_d_lit:
5000 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005001 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005002 break;
5003 case LDR_q_lit:
5004 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005005 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005006 break;
5007 case LDRSW_x_lit:
5008 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00005009 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005010 break;
5011
5012 // Ignore prfm hint instructions.
5013 case PRFM_lit:
5014 break;
5015
5016 default:
5017 VIXL_UNREACHABLE();
5018 }
5019
5020 local_monitor_.MaybeClear();
5021}
5022
5023
5024uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
5025 int64_t offset,
5026 AddrMode addrmode) {
5027 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
5028
5029 if ((addr_reg == 31) && ((address % 16) != 0)) {
5030 // When the base register is SP the stack pointer is required to be
5031 // quadword aligned prior to the address calculation and write-backs.
5032 // Misalignment will cause a stack alignment fault.
5033 VIXL_ALIGNMENT_EXCEPTION();
5034 }
5035
5036 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
5037 VIXL_ASSERT(offset != 0);
5038 // Only preindex should log the register update here. For Postindex, the
5039 // update will be printed automatically by LogWrittenRegisters _after_ the
5040 // memory access itself is logged.
5041 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5042 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5043 }
5044
5045 if ((addrmode == Offset) || (addrmode == PreIndex)) {
5046 address += offset;
5047 }
5048
5049 // Verify that the calculated address is available to the host.
5050 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5051
5052 return static_cast<uintptr_t>(address);
5053}
5054
5055
5056void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5057 MoveWideImmediateOp mov_op =
5058 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5059 int64_t new_xn_val = 0;
5060
5061 bool is_64_bits = instr->GetSixtyFourBits() == 1;
5062 // Shift is limited for W operations.
5063 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5064
5065 // Get the shifted immediate.
5066 int64_t shift = instr->GetShiftMoveWide() * 16;
5067 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5068 << shift;
5069
5070 // Compute the new value.
5071 switch (mov_op) {
5072 case MOVN_w:
5073 case MOVN_x: {
5074 new_xn_val = ~shifted_imm16;
5075 if (!is_64_bits) new_xn_val &= kWRegMask;
5076 break;
5077 }
5078 case MOVK_w:
5079 case MOVK_x: {
5080 unsigned reg_code = instr->GetRd();
5081 int64_t prev_xn_val =
5082 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5083 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5084 break;
5085 }
5086 case MOVZ_w:
5087 case MOVZ_x: {
5088 new_xn_val = shifted_imm16;
5089 break;
5090 }
5091 default:
5092 VIXL_UNREACHABLE();
5093 }
5094
5095 // Update the destination register.
5096 WriteXRegister(instr->GetRd(), new_xn_val);
5097}
5098
5099
5100void Simulator::VisitConditionalSelect(const Instruction* instr) {
5101 uint64_t new_val = ReadXRegister(instr->GetRn());
5102
5103 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5104 new_val = ReadXRegister(instr->GetRm());
5105 switch (instr->Mask(ConditionalSelectMask)) {
5106 case CSEL_w:
5107 case CSEL_x:
5108 break;
5109 case CSINC_w:
5110 case CSINC_x:
5111 new_val++;
5112 break;
5113 case CSINV_w:
5114 case CSINV_x:
5115 new_val = ~new_val;
5116 break;
5117 case CSNEG_w:
5118 case CSNEG_x:
5119 new_val = -new_val;
5120 break;
5121 default:
5122 VIXL_UNIMPLEMENTED();
5123 }
5124 }
5125 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5126 WriteRegister(reg_size, instr->GetRd(), new_val);
5127}
5128
5129
Jacob Bramleyca789742018-09-13 14:25:46 +01005130// clang-format off
5131#define PAUTH_MODES(V) \
5132 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
5133 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
5134 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
5135 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
5136 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
5137 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
5138 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
5139 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
5140// clang-format on
5141
Alexandre Ramesd3832962016-07-04 15:03:43 +01005142void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5143 unsigned dst = instr->GetRd();
5144 unsigned src = instr->GetRn();
5145
5146 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005147#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
5148 case PAC##SUFFIX: { \
5149 uint64_t ptr = ReadXRegister(dst); \
5150 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
5151 break; \
5152 } \
5153 case AUT##SUFFIX: { \
5154 uint64_t ptr = ReadXRegister(dst); \
5155 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
5156 break; \
5157 }
5158
5159 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
5160#undef DEFINE_PAUTH_FUNCS
5161
5162 case XPACI:
5163 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5164 break;
5165 case XPACD:
5166 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5167 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005168 case RBIT_w:
5169 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5170 break;
5171 case RBIT_x:
5172 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5173 break;
5174 case REV16_w:
5175 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5176 break;
5177 case REV16_x:
5178 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5179 break;
5180 case REV_w:
5181 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5182 break;
5183 case REV32_x:
5184 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5185 break;
5186 case REV_x:
5187 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5188 break;
5189 case CLZ_w:
5190 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5191 break;
5192 case CLZ_x:
5193 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5194 break;
5195 case CLS_w:
5196 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5197 break;
5198 case CLS_x:
5199 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5200 break;
5201 default:
5202 VIXL_UNIMPLEMENTED();
5203 }
5204}
5205
5206
5207uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5208 VIXL_ASSERT((n > 32) && (n <= 64));
5209 for (unsigned i = (n - 1); i >= 32; i--) {
5210 if (((data >> i) & 1) != 0) {
5211 uint64_t polysh32 = (uint64_t)poly << (i - 32);
5212 uint64_t mask = (UINT64_C(1) << i) - 1;
5213 data = ((data & mask) ^ polysh32);
5214 }
5215 }
5216 return data & 0xffffffff;
5217}
5218
5219
5220template <typename T>
5221uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5222 unsigned size = sizeof(val) * 8; // Number of bits in type T.
5223 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5224 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5225 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5226 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5227}
5228
5229
5230uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5231 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5232 // the CRC of each 32-bit word sequentially.
5233 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5234 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5235}
5236
5237
5238void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5239 Shift shift_op = NO_SHIFT;
5240 int64_t result = 0;
5241 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5242
5243 switch (instr->Mask(DataProcessing2SourceMask)) {
5244 case SDIV_w: {
5245 int32_t rn = ReadWRegister(instr->GetRn());
5246 int32_t rm = ReadWRegister(instr->GetRm());
5247 if ((rn == kWMinInt) && (rm == -1)) {
5248 result = kWMinInt;
5249 } else if (rm == 0) {
5250 // Division by zero can be trapped, but not on A-class processors.
5251 result = 0;
5252 } else {
5253 result = rn / rm;
5254 }
5255 break;
5256 }
5257 case SDIV_x: {
5258 int64_t rn = ReadXRegister(instr->GetRn());
5259 int64_t rm = ReadXRegister(instr->GetRm());
5260 if ((rn == kXMinInt) && (rm == -1)) {
5261 result = kXMinInt;
5262 } else if (rm == 0) {
5263 // Division by zero can be trapped, but not on A-class processors.
5264 result = 0;
5265 } else {
5266 result = rn / rm;
5267 }
5268 break;
5269 }
5270 case UDIV_w: {
5271 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5272 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5273 if (rm == 0) {
5274 // Division by zero can be trapped, but not on A-class processors.
5275 result = 0;
5276 } else {
5277 result = rn / rm;
5278 }
5279 break;
5280 }
5281 case UDIV_x: {
5282 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5283 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5284 if (rm == 0) {
5285 // Division by zero can be trapped, but not on A-class processors.
5286 result = 0;
5287 } else {
5288 result = rn / rm;
5289 }
5290 break;
5291 }
5292 case LSLV_w:
5293 case LSLV_x:
5294 shift_op = LSL;
5295 break;
5296 case LSRV_w:
5297 case LSRV_x:
5298 shift_op = LSR;
5299 break;
5300 case ASRV_w:
5301 case ASRV_x:
5302 shift_op = ASR;
5303 break;
5304 case RORV_w:
5305 case RORV_x:
5306 shift_op = ROR;
5307 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005308 case PACGA: {
5309 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5310 uint64_t src = static_cast<uint64_t>(
5311 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5312 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5313 result = code & 0xffffffff00000000;
5314 break;
5315 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005316 case CRC32B: {
5317 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5318 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5319 result = Crc32Checksum(acc, val, CRC32_POLY);
5320 break;
5321 }
5322 case CRC32H: {
5323 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5324 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5325 result = Crc32Checksum(acc, val, CRC32_POLY);
5326 break;
5327 }
5328 case CRC32W: {
5329 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5330 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5331 result = Crc32Checksum(acc, val, CRC32_POLY);
5332 break;
5333 }
5334 case CRC32X: {
5335 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5336 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5337 result = Crc32Checksum(acc, val, CRC32_POLY);
5338 reg_size = kWRegSize;
5339 break;
5340 }
5341 case CRC32CB: {
5342 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5343 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5344 result = Crc32Checksum(acc, val, CRC32C_POLY);
5345 break;
5346 }
5347 case CRC32CH: {
5348 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5349 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5350 result = Crc32Checksum(acc, val, CRC32C_POLY);
5351 break;
5352 }
5353 case CRC32CW: {
5354 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5355 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5356 result = Crc32Checksum(acc, val, CRC32C_POLY);
5357 break;
5358 }
5359 case CRC32CX: {
5360 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5361 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5362 result = Crc32Checksum(acc, val, CRC32C_POLY);
5363 reg_size = kWRegSize;
5364 break;
5365 }
5366 default:
5367 VIXL_UNIMPLEMENTED();
5368 }
5369
5370 if (shift_op != NO_SHIFT) {
5371 // Shift distance encoded in the least-significant five/six bits of the
5372 // register.
5373 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5374 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5375 result = ShiftOperand(reg_size,
5376 ReadRegister(reg_size, instr->GetRn()),
5377 shift_op,
5378 shift);
5379 }
5380 WriteRegister(reg_size, instr->GetRd(), result);
5381}
5382
5383
Alexandre Ramesd3832962016-07-04 15:03:43 +01005384void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5385 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5386
5387 uint64_t result = 0;
5388 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5389 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5390 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5391 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5392 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005393 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5394 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005395 switch (instr->Mask(DataProcessing3SourceMask)) {
5396 case MADD_w:
5397 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005398 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005399 break;
5400 case MSUB_w:
5401 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005402 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005403 break;
5404 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005405 result = ReadXRegister(instr->GetRa()) +
5406 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005407 break;
5408 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005409 result = ReadXRegister(instr->GetRa()) -
5410 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005411 break;
5412 case UMADDL_x:
5413 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5414 break;
5415 case UMSUBL_x:
5416 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5417 break;
5418 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005419 result =
5420 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5421 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005422 break;
5423 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07005424 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5425 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005426 break;
5427 default:
5428 VIXL_UNIMPLEMENTED();
5429 }
5430 WriteRegister(reg_size, instr->GetRd(), result);
5431}
5432
5433
5434void Simulator::VisitBitfield(const Instruction* instr) {
5435 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5436 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005437 int R = instr->GetImmR();
5438 int S = instr->GetImmS();
5439 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005440 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005441 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005442 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005443 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005444 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005445 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005446 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005447 diff += reg_size;
5448 }
5449
5450 // inzero indicates if the extracted bitfield is inserted into the
5451 // destination register value or in zero.
5452 // If extend is true, extend the sign of the extracted bitfield.
5453 bool inzero = false;
5454 bool extend = false;
5455 switch (instr->Mask(BitfieldMask)) {
5456 case BFM_x:
5457 case BFM_w:
5458 break;
5459 case SBFM_x:
5460 case SBFM_w:
5461 inzero = true;
5462 extend = true;
5463 break;
5464 case UBFM_x:
5465 case UBFM_w:
5466 inzero = true;
5467 break;
5468 default:
5469 VIXL_UNIMPLEMENTED();
5470 }
5471
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005472 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5473 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005474 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00005475 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005476 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00005477 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5478 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005479
5480 // Merge sign extension, dest/zero and bitfield.
5481 result = signbits | (result & mask) | (dst & ~mask);
5482
5483 WriteRegister(reg_size, instr->GetRd(), result);
5484}
5485
5486
5487void Simulator::VisitExtract(const Instruction* instr) {
5488 unsigned lsb = instr->GetImmS();
5489 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5490 uint64_t low_res =
5491 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00005492 uint64_t high_res = (lsb == 0)
5493 ? 0
5494 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5495 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005496 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5497}
5498
5499
5500void Simulator::VisitFPImmediate(const Instruction* instr) {
5501 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005502 unsigned dest = instr->GetRd();
5503 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01005504 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01005505 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01005506 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005507 case FMOV_s_imm:
5508 WriteSRegister(dest, instr->GetImmFP32());
5509 break;
5510 case FMOV_d_imm:
5511 WriteDRegister(dest, instr->GetImmFP64());
5512 break;
5513 default:
5514 VIXL_UNREACHABLE();
5515 }
5516}
5517
5518
5519void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5520 AssertSupportedFPCR();
5521
5522 unsigned dst = instr->GetRd();
5523 unsigned src = instr->GetRn();
5524
5525 FPRounding round = ReadRMode();
5526
5527 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005528 case FCVTAS_wh:
5529 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5530 break;
5531 case FCVTAS_xh:
5532 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5533 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005534 case FCVTAS_ws:
5535 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5536 break;
5537 case FCVTAS_xs:
5538 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5539 break;
5540 case FCVTAS_wd:
5541 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5542 break;
5543 case FCVTAS_xd:
5544 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5545 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005546 case FCVTAU_wh:
5547 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5548 break;
5549 case FCVTAU_xh:
5550 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5551 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005552 case FCVTAU_ws:
5553 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5554 break;
5555 case FCVTAU_xs:
5556 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5557 break;
5558 case FCVTAU_wd:
5559 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5560 break;
5561 case FCVTAU_xd:
5562 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5563 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005564 case FCVTMS_wh:
5565 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5566 break;
5567 case FCVTMS_xh:
5568 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5569 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005570 case FCVTMS_ws:
5571 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5572 break;
5573 case FCVTMS_xs:
5574 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5575 break;
5576 case FCVTMS_wd:
5577 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5578 break;
5579 case FCVTMS_xd:
5580 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5581 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005582 case FCVTMU_wh:
5583 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5584 break;
5585 case FCVTMU_xh:
5586 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5587 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005588 case FCVTMU_ws:
5589 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5590 break;
5591 case FCVTMU_xs:
5592 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5593 break;
5594 case FCVTMU_wd:
5595 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5596 break;
5597 case FCVTMU_xd:
5598 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5599 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005600 case FCVTPS_wh:
5601 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5602 break;
5603 case FCVTPS_xh:
5604 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5605 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005606 case FCVTPS_ws:
5607 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5608 break;
5609 case FCVTPS_xs:
5610 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5611 break;
5612 case FCVTPS_wd:
5613 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5614 break;
5615 case FCVTPS_xd:
5616 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5617 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005618 case FCVTPU_wh:
5619 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5620 break;
5621 case FCVTPU_xh:
5622 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5623 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005624 case FCVTPU_ws:
5625 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5626 break;
5627 case FCVTPU_xs:
5628 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5629 break;
5630 case FCVTPU_wd:
5631 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5632 break;
5633 case FCVTPU_xd:
5634 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5635 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005636 case FCVTNS_wh:
5637 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5638 break;
5639 case FCVTNS_xh:
5640 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5641 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005642 case FCVTNS_ws:
5643 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5644 break;
5645 case FCVTNS_xs:
5646 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5647 break;
5648 case FCVTNS_wd:
5649 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5650 break;
5651 case FCVTNS_xd:
5652 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5653 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005654 case FCVTNU_wh:
5655 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5656 break;
5657 case FCVTNU_xh:
5658 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5659 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005660 case FCVTNU_ws:
5661 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5662 break;
5663 case FCVTNU_xs:
5664 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5665 break;
5666 case FCVTNU_wd:
5667 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5668 break;
5669 case FCVTNU_xd:
5670 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5671 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005672 case FCVTZS_wh:
5673 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5674 break;
5675 case FCVTZS_xh:
5676 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5677 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005678 case FCVTZS_ws:
5679 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5680 break;
5681 case FCVTZS_xs:
5682 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5683 break;
5684 case FCVTZS_wd:
5685 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5686 break;
5687 case FCVTZS_xd:
5688 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5689 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005690 case FCVTZU_wh:
5691 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5692 break;
5693 case FCVTZU_xh:
5694 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5695 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005696 case FCVTZU_ws:
5697 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5698 break;
5699 case FCVTZU_xs:
5700 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5701 break;
5702 case FCVTZU_wd:
5703 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5704 break;
5705 case FCVTZU_xd:
5706 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5707 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005708 case FJCVTZS:
5709 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5710 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005711 case FMOV_hw:
5712 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5713 break;
5714 case FMOV_wh:
5715 WriteWRegister(dst, ReadHRegisterBits(src));
5716 break;
5717 case FMOV_xh:
5718 WriteXRegister(dst, ReadHRegisterBits(src));
5719 break;
5720 case FMOV_hx:
5721 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5722 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005723 case FMOV_ws:
5724 WriteWRegister(dst, ReadSRegisterBits(src));
5725 break;
5726 case FMOV_xd:
5727 WriteXRegister(dst, ReadDRegisterBits(src));
5728 break;
5729 case FMOV_sw:
5730 WriteSRegisterBits(dst, ReadWRegister(src));
5731 break;
5732 case FMOV_dx:
5733 WriteDRegisterBits(dst, ReadXRegister(src));
5734 break;
5735 case FMOV_d1_x:
5736 LogicVRegister(ReadVRegister(dst))
5737 .SetUint(kFormatD, 1, ReadXRegister(src));
5738 break;
5739 case FMOV_x_d1:
5740 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5741 break;
5742
5743 // A 32-bit input can be handled in the same way as a 64-bit input, since
5744 // the sign- or zero-extension will not affect the conversion.
5745 case SCVTF_dx:
5746 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5747 break;
5748 case SCVTF_dw:
5749 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5750 break;
5751 case UCVTF_dx:
5752 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5753 break;
5754 case UCVTF_dw: {
5755 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005756 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005757 break;
5758 }
5759 case SCVTF_sx:
5760 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5761 break;
5762 case SCVTF_sw:
5763 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5764 break;
5765 case UCVTF_sx:
5766 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5767 break;
5768 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01005769 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5770 break;
5771 }
5772 case SCVTF_hx:
5773 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5774 break;
5775 case SCVTF_hw:
5776 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5777 break;
5778 case UCVTF_hx:
5779 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5780 break;
5781 case UCVTF_hw: {
5782 WriteHRegister(dst,
5783 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005784 break;
5785 }
5786
5787 default:
5788 VIXL_UNREACHABLE();
5789 }
5790}
5791
5792
5793void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5794 AssertSupportedFPCR();
5795
5796 unsigned dst = instr->GetRd();
5797 unsigned src = instr->GetRn();
5798 int fbits = 64 - instr->GetFPScale();
5799
5800 FPRounding round = ReadRMode();
5801
5802 switch (instr->Mask(FPFixedPointConvertMask)) {
5803 // A 32-bit input can be handled in the same way as a 64-bit input, since
5804 // the sign- or zero-extension will not affect the conversion.
5805 case SCVTF_dx_fixed:
5806 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5807 break;
5808 case SCVTF_dw_fixed:
5809 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5810 break;
5811 case UCVTF_dx_fixed:
5812 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5813 break;
5814 case UCVTF_dw_fixed: {
5815 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005816 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005817 break;
5818 }
5819 case SCVTF_sx_fixed:
5820 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5821 break;
5822 case SCVTF_sw_fixed:
5823 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5824 break;
5825 case UCVTF_sx_fixed:
5826 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5827 break;
5828 case UCVTF_sw_fixed: {
5829 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01005830 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5831 break;
5832 }
5833 case SCVTF_hx_fixed:
5834 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5835 break;
5836 case SCVTF_hw_fixed:
5837 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5838 break;
5839 case UCVTF_hx_fixed:
5840 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5841 break;
5842 case UCVTF_hw_fixed: {
5843 WriteHRegister(dst,
5844 UFixedToFloat16(ReadRegister<uint32_t>(src),
5845 fbits,
5846 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005847 break;
5848 }
5849 case FCVTZS_xd_fixed:
5850 WriteXRegister(dst,
5851 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5852 FPZero));
5853 break;
5854 case FCVTZS_wd_fixed:
5855 WriteWRegister(dst,
5856 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5857 FPZero));
5858 break;
5859 case FCVTZU_xd_fixed:
5860 WriteXRegister(dst,
5861 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5862 FPZero));
5863 break;
5864 case FCVTZU_wd_fixed:
5865 WriteWRegister(dst,
5866 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5867 FPZero));
5868 break;
5869 case FCVTZS_xs_fixed:
5870 WriteXRegister(dst,
5871 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5872 FPZero));
5873 break;
5874 case FCVTZS_ws_fixed:
5875 WriteWRegister(dst,
5876 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5877 FPZero));
5878 break;
5879 case FCVTZU_xs_fixed:
5880 WriteXRegister(dst,
5881 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5882 FPZero));
5883 break;
5884 case FCVTZU_ws_fixed:
5885 WriteWRegister(dst,
5886 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5887 FPZero));
5888 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005889 case FCVTZS_xh_fixed: {
5890 double output =
5891 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5892 WriteXRegister(dst, FPToInt64(output, FPZero));
5893 break;
5894 }
5895 case FCVTZS_wh_fixed: {
5896 double output =
5897 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5898 WriteWRegister(dst, FPToInt32(output, FPZero));
5899 break;
5900 }
5901 case FCVTZU_xh_fixed: {
5902 double output =
5903 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5904 WriteXRegister(dst, FPToUInt64(output, FPZero));
5905 break;
5906 }
5907 case FCVTZU_wh_fixed: {
5908 double output =
5909 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5910 WriteWRegister(dst, FPToUInt32(output, FPZero));
5911 break;
5912 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005913 default:
5914 VIXL_UNREACHABLE();
5915 }
5916}
5917
5918
5919void Simulator::VisitFPCompare(const Instruction* instr) {
5920 AssertSupportedFPCR();
5921
5922 FPTrapFlags trap = DisableTrap;
5923 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005924 case FCMPE_h:
5925 trap = EnableTrap;
5926 VIXL_FALLTHROUGH();
5927 case FCMP_h:
5928 FPCompare(ReadHRegister(instr->GetRn()),
5929 ReadHRegister(instr->GetRm()),
5930 trap);
5931 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005932 case FCMPE_s:
5933 trap = EnableTrap;
5934 VIXL_FALLTHROUGH();
5935 case FCMP_s:
5936 FPCompare(ReadSRegister(instr->GetRn()),
5937 ReadSRegister(instr->GetRm()),
5938 trap);
5939 break;
5940 case FCMPE_d:
5941 trap = EnableTrap;
5942 VIXL_FALLTHROUGH();
5943 case FCMP_d:
5944 FPCompare(ReadDRegister(instr->GetRn()),
5945 ReadDRegister(instr->GetRm()),
5946 trap);
5947 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005948 case FCMPE_h_zero:
5949 trap = EnableTrap;
5950 VIXL_FALLTHROUGH();
5951 case FCMP_h_zero:
5952 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5953 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005954 case FCMPE_s_zero:
5955 trap = EnableTrap;
5956 VIXL_FALLTHROUGH();
5957 case FCMP_s_zero:
5958 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
5959 break;
5960 case FCMPE_d_zero:
5961 trap = EnableTrap;
5962 VIXL_FALLTHROUGH();
5963 case FCMP_d_zero:
5964 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
5965 break;
5966 default:
5967 VIXL_UNIMPLEMENTED();
5968 }
5969}
5970
5971
5972void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
5973 AssertSupportedFPCR();
5974
5975 FPTrapFlags trap = DisableTrap;
5976 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005977 case FCCMPE_h:
5978 trap = EnableTrap;
5979 VIXL_FALLTHROUGH();
5980 case FCCMP_h:
5981 if (ConditionPassed(instr->GetCondition())) {
5982 FPCompare(ReadHRegister(instr->GetRn()),
5983 ReadHRegister(instr->GetRm()),
5984 trap);
5985 } else {
5986 ReadNzcv().SetFlags(instr->GetNzcv());
5987 LogSystemRegister(NZCV);
5988 }
5989 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005990 case FCCMPE_s:
5991 trap = EnableTrap;
5992 VIXL_FALLTHROUGH();
5993 case FCCMP_s:
5994 if (ConditionPassed(instr->GetCondition())) {
5995 FPCompare(ReadSRegister(instr->GetRn()),
5996 ReadSRegister(instr->GetRm()),
5997 trap);
5998 } else {
5999 ReadNzcv().SetFlags(instr->GetNzcv());
6000 LogSystemRegister(NZCV);
6001 }
6002 break;
6003 case FCCMPE_d:
6004 trap = EnableTrap;
6005 VIXL_FALLTHROUGH();
6006 case FCCMP_d:
6007 if (ConditionPassed(instr->GetCondition())) {
6008 FPCompare(ReadDRegister(instr->GetRn()),
6009 ReadDRegister(instr->GetRm()),
6010 trap);
6011 } else {
6012 ReadNzcv().SetFlags(instr->GetNzcv());
6013 LogSystemRegister(NZCV);
6014 }
6015 break;
6016 default:
6017 VIXL_UNIMPLEMENTED();
6018 }
6019}
6020
6021
6022void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
6023 AssertSupportedFPCR();
6024
6025 Instr selected;
6026 if (ConditionPassed(instr->GetCondition())) {
6027 selected = instr->GetRn();
6028 } else {
6029 selected = instr->GetRm();
6030 }
6031
6032 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006033 case FCSEL_h:
6034 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
6035 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006036 case FCSEL_s:
6037 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
6038 break;
6039 case FCSEL_d:
6040 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6041 break;
6042 default:
6043 VIXL_UNIMPLEMENTED();
6044 }
6045}
6046
6047
6048void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6049 AssertSupportedFPCR();
6050
6051 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006052 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006053 switch (instr->Mask(FPTypeMask)) {
6054 default:
6055 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6056 case FP64:
6057 vform = kFormatD;
6058 break;
6059 case FP32:
6060 vform = kFormatS;
6061 break;
6062 case FP16:
6063 vform = kFormatH;
6064 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006065 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006066
Alexandre Ramesd3832962016-07-04 15:03:43 +01006067 SimVRegister& rd = ReadVRegister(instr->GetRd());
6068 SimVRegister& rn = ReadVRegister(instr->GetRn());
6069 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006070 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006071
6072 unsigned fd = instr->GetRd();
6073 unsigned fn = instr->GetRn();
6074
6075 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01006076 case FMOV_h:
6077 WriteHRegister(fd, ReadHRegister(fn));
6078 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006079 case FMOV_s:
6080 WriteSRegister(fd, ReadSRegister(fn));
6081 return;
6082 case FMOV_d:
6083 WriteDRegister(fd, ReadDRegister(fn));
6084 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006085 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006086 case FABS_s:
6087 case FABS_d:
6088 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6089 // Explicitly log the register update whilst we have type information.
6090 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6091 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006092 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006093 case FNEG_s:
6094 case FNEG_d:
6095 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6096 // Explicitly log the register update whilst we have type information.
6097 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6098 return;
6099 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01006100 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006101 return;
6102 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01006103 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006104 return;
6105 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01006106 WriteHRegister(fd,
6107 Float16ToRawbits(
6108 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006109 return;
6110 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01006111 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006112 return;
6113 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01006114 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006115 return;
6116 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01006117 WriteHRegister(fd,
6118 Float16ToRawbits(
6119 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006120 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01006121 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006122 case FSQRT_s:
6123 case FSQRT_d:
6124 fsqrt(vform, rd, rn);
6125 // Explicitly log the register update whilst we have type information.
6126 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6127 return;
TatWai Chong04471812019-03-19 14:29:00 -07006128 case FRINT32X_s:
6129 case FRINT32X_d:
6130 inexact_exception = true;
6131 frint_mode = kFrintToInt32;
6132 break; // Use FPCR rounding mode.
6133 case FRINT64X_s:
6134 case FRINT64X_d:
6135 inexact_exception = true;
6136 frint_mode = kFrintToInt64;
6137 break; // Use FPCR rounding mode.
6138 case FRINT32Z_s:
6139 case FRINT32Z_d:
6140 inexact_exception = true;
6141 frint_mode = kFrintToInt32;
6142 fpcr_rounding = FPZero;
6143 break;
6144 case FRINT64Z_s:
6145 case FRINT64Z_d:
6146 inexact_exception = true;
6147 frint_mode = kFrintToInt64;
6148 fpcr_rounding = FPZero;
6149 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006150 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006151 case FRINTI_s:
6152 case FRINTI_d:
6153 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01006154 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006155 case FRINTX_s:
6156 case FRINTX_d:
6157 inexact_exception = true;
6158 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006159 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006160 case FRINTA_s:
6161 case FRINTA_d:
6162 fpcr_rounding = FPTieAway;
6163 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006164 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006165 case FRINTM_s:
6166 case FRINTM_d:
6167 fpcr_rounding = FPNegativeInfinity;
6168 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006169 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006170 case FRINTN_s:
6171 case FRINTN_d:
6172 fpcr_rounding = FPTieEven;
6173 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006174 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006175 case FRINTP_s:
6176 case FRINTP_d:
6177 fpcr_rounding = FPPositiveInfinity;
6178 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006179 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006180 case FRINTZ_s:
6181 case FRINTZ_d:
6182 fpcr_rounding = FPZero;
6183 break;
6184 default:
6185 VIXL_UNIMPLEMENTED();
6186 }
6187
6188 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006189 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006190 // Explicitly log the register update whilst we have type information.
6191 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6192}
6193
6194
6195void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6196 AssertSupportedFPCR();
6197
Carey Williamsd8bb3572018-04-10 11:58:07 +01006198 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01006199 switch (instr->Mask(FPTypeMask)) {
6200 default:
6201 VIXL_UNREACHABLE_OR_FALLTHROUGH();
6202 case FP64:
6203 vform = kFormatD;
6204 break;
6205 case FP32:
6206 vform = kFormatS;
6207 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006208 case FP16:
6209 vform = kFormatH;
6210 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006211 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006212 SimVRegister& rd = ReadVRegister(instr->GetRd());
6213 SimVRegister& rn = ReadVRegister(instr->GetRn());
6214 SimVRegister& rm = ReadVRegister(instr->GetRm());
6215
6216 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006217 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006218 case FADD_s:
6219 case FADD_d:
6220 fadd(vform, rd, rn, rm);
6221 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006222 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006223 case FSUB_s:
6224 case FSUB_d:
6225 fsub(vform, rd, rn, rm);
6226 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006227 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006228 case FMUL_s:
6229 case FMUL_d:
6230 fmul(vform, rd, rn, rm);
6231 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006232 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006233 case FNMUL_s:
6234 case FNMUL_d:
6235 fnmul(vform, rd, rn, rm);
6236 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006237 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006238 case FDIV_s:
6239 case FDIV_d:
6240 fdiv(vform, rd, rn, rm);
6241 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006242 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006243 case FMAX_s:
6244 case FMAX_d:
6245 fmax(vform, rd, rn, rm);
6246 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006247 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006248 case FMIN_s:
6249 case FMIN_d:
6250 fmin(vform, rd, rn, rm);
6251 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006252 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006253 case FMAXNM_s:
6254 case FMAXNM_d:
6255 fmaxnm(vform, rd, rn, rm);
6256 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006257 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006258 case FMINNM_s:
6259 case FMINNM_d:
6260 fminnm(vform, rd, rn, rm);
6261 break;
6262 default:
6263 VIXL_UNREACHABLE();
6264 }
6265 // Explicitly log the register update whilst we have type information.
6266 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6267}
6268
6269
6270void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6271 AssertSupportedFPCR();
6272
6273 unsigned fd = instr->GetRd();
6274 unsigned fn = instr->GetRn();
6275 unsigned fm = instr->GetRm();
6276 unsigned fa = instr->GetRa();
6277
6278 switch (instr->Mask(FPDataProcessing3SourceMask)) {
6279 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01006280 case FMADD_h:
6281 WriteHRegister(fd,
6282 FPMulAdd(ReadHRegister(fa),
6283 ReadHRegister(fn),
6284 ReadHRegister(fm)));
6285 break;
6286 case FMSUB_h:
6287 WriteHRegister(fd,
6288 FPMulAdd(ReadHRegister(fa),
6289 -ReadHRegister(fn),
6290 ReadHRegister(fm)));
6291 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006292 case FMADD_s:
6293 WriteSRegister(fd,
6294 FPMulAdd(ReadSRegister(fa),
6295 ReadSRegister(fn),
6296 ReadSRegister(fm)));
6297 break;
6298 case FMSUB_s:
6299 WriteSRegister(fd,
6300 FPMulAdd(ReadSRegister(fa),
6301 -ReadSRegister(fn),
6302 ReadSRegister(fm)));
6303 break;
6304 case FMADD_d:
6305 WriteDRegister(fd,
6306 FPMulAdd(ReadDRegister(fa),
6307 ReadDRegister(fn),
6308 ReadDRegister(fm)));
6309 break;
6310 case FMSUB_d:
6311 WriteDRegister(fd,
6312 FPMulAdd(ReadDRegister(fa),
6313 -ReadDRegister(fn),
6314 ReadDRegister(fm)));
6315 break;
6316 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01006317 case FNMADD_h:
6318 WriteHRegister(fd,
6319 FPMulAdd(-ReadHRegister(fa),
6320 -ReadHRegister(fn),
6321 ReadHRegister(fm)));
6322 break;
6323 case FNMSUB_h:
6324 WriteHRegister(fd,
6325 FPMulAdd(-ReadHRegister(fa),
6326 ReadHRegister(fn),
6327 ReadHRegister(fm)));
6328 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006329 case FNMADD_s:
6330 WriteSRegister(fd,
6331 FPMulAdd(-ReadSRegister(fa),
6332 -ReadSRegister(fn),
6333 ReadSRegister(fm)));
6334 break;
6335 case FNMSUB_s:
6336 WriteSRegister(fd,
6337 FPMulAdd(-ReadSRegister(fa),
6338 ReadSRegister(fn),
6339 ReadSRegister(fm)));
6340 break;
6341 case FNMADD_d:
6342 WriteDRegister(fd,
6343 FPMulAdd(-ReadDRegister(fa),
6344 -ReadDRegister(fn),
6345 ReadDRegister(fm)));
6346 break;
6347 case FNMSUB_d:
6348 WriteDRegister(fd,
6349 FPMulAdd(-ReadDRegister(fa),
6350 ReadDRegister(fn),
6351 ReadDRegister(fm)));
6352 break;
6353 default:
6354 VIXL_UNIMPLEMENTED();
6355 }
6356}
6357
6358
6359bool Simulator::FPProcessNaNs(const Instruction* instr) {
6360 unsigned fd = instr->GetRd();
6361 unsigned fn = instr->GetRn();
6362 unsigned fm = instr->GetRm();
6363 bool done = false;
6364
6365 if (instr->Mask(FP64) == FP64) {
6366 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006367 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006368 WriteDRegister(fd, result);
6369 done = true;
6370 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006371 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006372 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01006373 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006374 WriteSRegister(fd, result);
6375 done = true;
6376 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006377 } else {
6378 VIXL_ASSERT(instr->Mask(FP16) == FP16);
6379 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006380 }
6381
6382 return done;
6383}
6384
6385
6386void Simulator::SysOp_W(int op, int64_t val) {
6387 switch (op) {
6388 case IVAU:
6389 case CVAC:
6390 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01006391 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08006392 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006393 case CIVAC: {
6394 // Perform a dummy memory access to ensure that we have read access
6395 // to the specified address.
6396 volatile uint8_t y = Memory::Read<uint8_t>(val);
6397 USE(y);
6398 // TODO: Implement "case ZVA:".
6399 break;
6400 }
6401 default:
6402 VIXL_UNIMPLEMENTED();
6403 }
6404}
6405
6406
Jacob Bramleyca789742018-09-13 14:25:46 +01006407// clang-format off
6408#define PAUTH_SYSTEM_MODES(V) \
6409 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
6410 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
6411 V(AZ, 30, 0x00000000, kPACKeyIA) \
6412 V(BZ, 30, 0x00000000, kPACKeyIB) \
6413 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6414 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6415// clang-format on
6416
6417
Alexandre Ramesd3832962016-07-04 15:03:43 +01006418void Simulator::VisitSystem(const Instruction* instr) {
6419 // Some system instructions hijack their Op and Cp fields to represent a
6420 // range of immediates instead of indicating a different instruction. This
6421 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01006422 if (instr->GetInstructionBits() == XPACLRI) {
6423 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00006424 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6425 switch (instr->Mask(SystemPStateMask)) {
6426 case CFINV:
6427 ReadNzcv().SetC(!ReadC());
6428 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00006429 case AXFLAG:
6430 ReadNzcv().SetN(0);
6431 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6432 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6433 ReadNzcv().SetV(0);
6434 break;
6435 case XAFLAG: {
6436 // Can't set the flags in place due to the logical dependencies.
6437 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6438 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6439 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6440 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6441 ReadNzcv().SetN(n);
6442 ReadNzcv().SetZ(z);
6443 ReadNzcv().SetC(c);
6444 ReadNzcv().SetV(v);
6445 break;
6446 }
Alexander Gilday2487f142018-11-05 13:07:27 +00006447 }
Jacob Bramleyca789742018-09-13 14:25:46 +01006448 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006449 // Check BType allows PACI[AB]SP instructions.
6450 if (PcIsInGuardedPage()) {
6451 Instr i = instr->Mask(SystemPAuthMask);
6452 if ((i == PACIASP) || (i == PACIBSP)) {
6453 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01006454 case BranchFromGuardedNotToIP:
6455 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6456 // assume here to be zero. This allows execution of PACI[AB]SP when
6457 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00006458 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006459 case BranchFromUnguardedOrToIP:
6460 case BranchAndLink:
6461 break;
6462 }
6463 }
6464 }
6465
Jacob Bramleyca789742018-09-13 14:25:46 +01006466 switch (instr->Mask(SystemPAuthMask)) {
6467#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
6468 case PACI##SUFFIX: \
6469 WriteXRegister(DST, \
6470 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6471 break; \
6472 case AUTI##SUFFIX: \
6473 WriteXRegister(DST, \
6474 AuthPAC(ReadXRegister(DST), \
6475 MOD, \
6476 KEY, \
6477 kInstructionPointer)); \
6478 break;
6479
6480 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6481#undef DEFINE_PAUTH_FUNCS
6482 }
6483 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6484 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006485 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6486 switch (instr->Mask(SystemExclusiveMonitorMask)) {
6487 case CLREX: {
6488 PrintExclusiveAccessWarning();
6489 ClearLocalMonitor();
6490 break;
6491 }
6492 }
6493 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6494 switch (instr->Mask(SystemSysRegMask)) {
6495 case MRS: {
6496 switch (instr->GetImmSystemRegister()) {
6497 case NZCV:
6498 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6499 break;
6500 case FPCR:
6501 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6502 break;
TatWai Chong04edf682018-12-27 16:01:02 -08006503 case RNDR:
6504 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00006505 uint64_t high = jrand48(rand_state_);
6506 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08006507 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6508 WriteXRegister(instr->GetRt(), rand_num);
6509 // Simulate successful random number generation.
6510 // TODO: Return failure occasionally as a random number cannot be
6511 // returned in a period of time.
6512 ReadNzcv().SetRawValue(NoFlag);
6513 LogSystemRegister(NZCV);
6514 break;
6515 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006516 default:
6517 VIXL_UNIMPLEMENTED();
6518 }
6519 break;
6520 }
6521 case MSR: {
6522 switch (instr->GetImmSystemRegister()) {
6523 case NZCV:
6524 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6525 LogSystemRegister(NZCV);
6526 break;
6527 case FPCR:
6528 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6529 LogSystemRegister(FPCR);
6530 break;
6531 default:
6532 VIXL_UNIMPLEMENTED();
6533 }
6534 break;
6535 }
6536 }
6537 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6538 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6539 switch (instr->GetImmHint()) {
6540 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01006541 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00006542 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01006543 case BTI_jc:
6544 break;
6545 case BTI:
6546 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6547 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6548 }
6549 break;
6550 case BTI_c:
6551 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6552 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6553 }
6554 break;
6555 case BTI_j:
6556 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6557 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6558 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01006559 break;
6560 default:
6561 VIXL_UNIMPLEMENTED();
6562 }
6563 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6564 __sync_synchronize();
6565 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6566 switch (instr->Mask(SystemSysMask)) {
6567 case SYS:
6568 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6569 break;
6570 default:
6571 VIXL_UNIMPLEMENTED();
6572 }
6573 } else {
6574 VIXL_UNIMPLEMENTED();
6575 }
6576}
6577
6578
6579void Simulator::VisitException(const Instruction* instr) {
6580 switch (instr->Mask(ExceptionMask)) {
6581 case HLT:
6582 switch (instr->GetImmException()) {
6583 case kUnreachableOpcode:
6584 DoUnreachable(instr);
6585 return;
6586 case kTraceOpcode:
6587 DoTrace(instr);
6588 return;
6589 case kLogOpcode:
6590 DoLog(instr);
6591 return;
6592 case kPrintfOpcode:
6593 DoPrintf(instr);
6594 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01006595 case kRuntimeCallOpcode:
6596 DoRuntimeCall(instr);
6597 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01006598 case kSetCPUFeaturesOpcode:
6599 case kEnableCPUFeaturesOpcode:
6600 case kDisableCPUFeaturesOpcode:
6601 DoConfigureCPUFeatures(instr);
6602 return;
6603 case kSaveCPUFeaturesOpcode:
6604 DoSaveCPUFeatures(instr);
6605 return;
6606 case kRestoreCPUFeaturesOpcode:
6607 DoRestoreCPUFeatures(instr);
6608 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006609 default:
6610 HostBreakpoint();
6611 return;
6612 }
6613 case BRK:
6614 HostBreakpoint();
6615 return;
6616 default:
6617 VIXL_UNIMPLEMENTED();
6618 }
6619}
6620
6621
6622void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6623 VisitUnimplemented(instr);
6624}
6625
6626
6627void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6628 VisitUnimplemented(instr);
6629}
6630
6631
6632void Simulator::VisitCryptoAES(const Instruction* instr) {
6633 VisitUnimplemented(instr);
6634}
6635
6636
6637void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6638 NEONFormatDecoder nfd(instr);
6639 VectorFormat vf = nfd.GetVectorFormat();
6640
6641 static const NEONFormatMap map_lp =
6642 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6643 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6644
6645 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6646 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6647
6648 static const NEONFormatMap map_fcvtn = {{22, 30},
6649 {NF_4H, NF_8H, NF_2S, NF_4S}};
6650 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6651
6652 SimVRegister& rd = ReadVRegister(instr->GetRd());
6653 SimVRegister& rn = ReadVRegister(instr->GetRn());
6654
6655 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6656 // These instructions all use a two bit size field, except NOT and RBIT,
6657 // which use the field to encode the operation.
6658 switch (instr->Mask(NEON2RegMiscMask)) {
6659 case NEON_REV64:
6660 rev64(vf, rd, rn);
6661 break;
6662 case NEON_REV32:
6663 rev32(vf, rd, rn);
6664 break;
6665 case NEON_REV16:
6666 rev16(vf, rd, rn);
6667 break;
6668 case NEON_SUQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006669 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006670 break;
6671 case NEON_USQADD:
Martyn Capewell9b532192020-09-15 16:20:11 +01006672 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006673 break;
6674 case NEON_CLS:
6675 cls(vf, rd, rn);
6676 break;
6677 case NEON_CLZ:
6678 clz(vf, rd, rn);
6679 break;
6680 case NEON_CNT:
6681 cnt(vf, rd, rn);
6682 break;
6683 case NEON_SQABS:
6684 abs(vf, rd, rn).SignedSaturate(vf);
6685 break;
6686 case NEON_SQNEG:
6687 neg(vf, rd, rn).SignedSaturate(vf);
6688 break;
6689 case NEON_CMGT_zero:
6690 cmp(vf, rd, rn, 0, gt);
6691 break;
6692 case NEON_CMGE_zero:
6693 cmp(vf, rd, rn, 0, ge);
6694 break;
6695 case NEON_CMEQ_zero:
6696 cmp(vf, rd, rn, 0, eq);
6697 break;
6698 case NEON_CMLE_zero:
6699 cmp(vf, rd, rn, 0, le);
6700 break;
6701 case NEON_CMLT_zero:
6702 cmp(vf, rd, rn, 0, lt);
6703 break;
6704 case NEON_ABS:
6705 abs(vf, rd, rn);
6706 break;
6707 case NEON_NEG:
6708 neg(vf, rd, rn);
6709 break;
6710 case NEON_SADDLP:
6711 saddlp(vf_lp, rd, rn);
6712 break;
6713 case NEON_UADDLP:
6714 uaddlp(vf_lp, rd, rn);
6715 break;
6716 case NEON_SADALP:
6717 sadalp(vf_lp, rd, rn);
6718 break;
6719 case NEON_UADALP:
6720 uadalp(vf_lp, rd, rn);
6721 break;
6722 case NEON_RBIT_NOT:
6723 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6724 switch (instr->GetFPType()) {
6725 case 0:
6726 not_(vf, rd, rn);
6727 break;
6728 case 1:
6729 rbit(vf, rd, rn);
6730 break;
6731 default:
6732 VIXL_UNIMPLEMENTED();
6733 }
6734 break;
6735 }
6736 } else {
6737 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6738 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6739 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07006740 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006741
6742 // These instructions all use a one bit size field, except XTN, SQXTUN,
6743 // SHLL, SQXTN and UQXTN, which use a two bit size field.
6744 switch (instr->Mask(NEON2RegMiscFPMask)) {
6745 case NEON_FABS:
6746 fabs_(fpf, rd, rn);
6747 return;
6748 case NEON_FNEG:
6749 fneg(fpf, rd, rn);
6750 return;
6751 case NEON_FSQRT:
6752 fsqrt(fpf, rd, rn);
6753 return;
6754 case NEON_FCVTL:
6755 if (instr->Mask(NEON_Q)) {
6756 fcvtl2(vf_fcvtl, rd, rn);
6757 } else {
6758 fcvtl(vf_fcvtl, rd, rn);
6759 }
6760 return;
6761 case NEON_FCVTN:
6762 if (instr->Mask(NEON_Q)) {
6763 fcvtn2(vf_fcvtn, rd, rn);
6764 } else {
6765 fcvtn(vf_fcvtn, rd, rn);
6766 }
6767 return;
6768 case NEON_FCVTXN:
6769 if (instr->Mask(NEON_Q)) {
6770 fcvtxn2(vf_fcvtn, rd, rn);
6771 } else {
6772 fcvtxn(vf_fcvtn, rd, rn);
6773 }
6774 return;
6775
6776 // The following instructions break from the switch statement, rather
6777 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07006778 case NEON_FRINT32X:
6779 inexact_exception = true;
6780 frint_mode = kFrintToInt32;
6781 break; // Use FPCR rounding mode.
6782 case NEON_FRINT32Z:
6783 inexact_exception = true;
6784 frint_mode = kFrintToInt32;
6785 fpcr_rounding = FPZero;
6786 break;
6787 case NEON_FRINT64X:
6788 inexact_exception = true;
6789 frint_mode = kFrintToInt64;
6790 break; // Use FPCR rounding mode.
6791 case NEON_FRINT64Z:
6792 inexact_exception = true;
6793 frint_mode = kFrintToInt64;
6794 fpcr_rounding = FPZero;
6795 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006796 case NEON_FRINTI:
6797 break; // Use FPCR rounding mode.
6798 case NEON_FRINTX:
6799 inexact_exception = true;
6800 break;
6801 case NEON_FRINTA:
6802 fpcr_rounding = FPTieAway;
6803 break;
6804 case NEON_FRINTM:
6805 fpcr_rounding = FPNegativeInfinity;
6806 break;
6807 case NEON_FRINTN:
6808 fpcr_rounding = FPTieEven;
6809 break;
6810 case NEON_FRINTP:
6811 fpcr_rounding = FPPositiveInfinity;
6812 break;
6813 case NEON_FRINTZ:
6814 fpcr_rounding = FPZero;
6815 break;
6816
6817 case NEON_FCVTNS:
6818 fcvts(fpf, rd, rn, FPTieEven);
6819 return;
6820 case NEON_FCVTNU:
6821 fcvtu(fpf, rd, rn, FPTieEven);
6822 return;
6823 case NEON_FCVTPS:
6824 fcvts(fpf, rd, rn, FPPositiveInfinity);
6825 return;
6826 case NEON_FCVTPU:
6827 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6828 return;
6829 case NEON_FCVTMS:
6830 fcvts(fpf, rd, rn, FPNegativeInfinity);
6831 return;
6832 case NEON_FCVTMU:
6833 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6834 return;
6835 case NEON_FCVTZS:
6836 fcvts(fpf, rd, rn, FPZero);
6837 return;
6838 case NEON_FCVTZU:
6839 fcvtu(fpf, rd, rn, FPZero);
6840 return;
6841 case NEON_FCVTAS:
6842 fcvts(fpf, rd, rn, FPTieAway);
6843 return;
6844 case NEON_FCVTAU:
6845 fcvtu(fpf, rd, rn, FPTieAway);
6846 return;
6847 case NEON_SCVTF:
6848 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6849 return;
6850 case NEON_UCVTF:
6851 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6852 return;
6853 case NEON_URSQRTE:
6854 ursqrte(fpf, rd, rn);
6855 return;
6856 case NEON_URECPE:
6857 urecpe(fpf, rd, rn);
6858 return;
6859 case NEON_FRSQRTE:
6860 frsqrte(fpf, rd, rn);
6861 return;
6862 case NEON_FRECPE:
6863 frecpe(fpf, rd, rn, fpcr_rounding);
6864 return;
6865 case NEON_FCMGT_zero:
6866 fcmp_zero(fpf, rd, rn, gt);
6867 return;
6868 case NEON_FCMGE_zero:
6869 fcmp_zero(fpf, rd, rn, ge);
6870 return;
6871 case NEON_FCMEQ_zero:
6872 fcmp_zero(fpf, rd, rn, eq);
6873 return;
6874 case NEON_FCMLE_zero:
6875 fcmp_zero(fpf, rd, rn, le);
6876 return;
6877 case NEON_FCMLT_zero:
6878 fcmp_zero(fpf, rd, rn, lt);
6879 return;
6880 default:
6881 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6882 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6883 switch (instr->Mask(NEON2RegMiscMask)) {
6884 case NEON_XTN:
6885 xtn(vf, rd, rn);
6886 return;
6887 case NEON_SQXTN:
6888 sqxtn(vf, rd, rn);
6889 return;
6890 case NEON_UQXTN:
6891 uqxtn(vf, rd, rn);
6892 return;
6893 case NEON_SQXTUN:
6894 sqxtun(vf, rd, rn);
6895 return;
6896 case NEON_SHLL:
6897 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6898 if (instr->Mask(NEON_Q)) {
6899 shll2(vf, rd, rn);
6900 } else {
6901 shll(vf, rd, rn);
6902 }
6903 return;
6904 default:
6905 VIXL_UNIMPLEMENTED();
6906 }
6907 } else {
6908 VIXL_UNIMPLEMENTED();
6909 }
6910 }
6911
6912 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07006913 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006914 }
6915}
6916
6917
Jacob Bramleyca789742018-09-13 14:25:46 +01006918void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6919 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6920 NEONFormatDecoder nfd(instr);
6921 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6922
6923 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6924
6925 SimVRegister& rd = ReadVRegister(instr->GetRd());
6926 SimVRegister& rn = ReadVRegister(instr->GetRn());
6927
6928 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6929 case NEON_SCVTF_H:
6930 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6931 return;
6932 case NEON_UCVTF_H:
6933 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6934 return;
6935 case NEON_FCVTNS_H:
6936 fcvts(fpf, rd, rn, FPTieEven);
6937 return;
6938 case NEON_FCVTNU_H:
6939 fcvtu(fpf, rd, rn, FPTieEven);
6940 return;
6941 case NEON_FCVTPS_H:
6942 fcvts(fpf, rd, rn, FPPositiveInfinity);
6943 return;
6944 case NEON_FCVTPU_H:
6945 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6946 return;
6947 case NEON_FCVTMS_H:
6948 fcvts(fpf, rd, rn, FPNegativeInfinity);
6949 return;
6950 case NEON_FCVTMU_H:
6951 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6952 return;
6953 case NEON_FCVTZS_H:
6954 fcvts(fpf, rd, rn, FPZero);
6955 return;
6956 case NEON_FCVTZU_H:
6957 fcvtu(fpf, rd, rn, FPZero);
6958 return;
6959 case NEON_FCVTAS_H:
6960 fcvts(fpf, rd, rn, FPTieAway);
6961 return;
6962 case NEON_FCVTAU_H:
6963 fcvtu(fpf, rd, rn, FPTieAway);
6964 return;
6965 case NEON_FRINTI_H:
6966 frint(fpf, rd, rn, fpcr_rounding, false);
6967 return;
6968 case NEON_FRINTX_H:
6969 frint(fpf, rd, rn, fpcr_rounding, true);
6970 return;
6971 case NEON_FRINTA_H:
6972 frint(fpf, rd, rn, FPTieAway, false);
6973 return;
6974 case NEON_FRINTM_H:
6975 frint(fpf, rd, rn, FPNegativeInfinity, false);
6976 return;
6977 case NEON_FRINTN_H:
6978 frint(fpf, rd, rn, FPTieEven, false);
6979 return;
6980 case NEON_FRINTP_H:
6981 frint(fpf, rd, rn, FPPositiveInfinity, false);
6982 return;
6983 case NEON_FRINTZ_H:
6984 frint(fpf, rd, rn, FPZero, false);
6985 return;
6986 case NEON_FABS_H:
6987 fabs_(fpf, rd, rn);
6988 return;
6989 case NEON_FNEG_H:
6990 fneg(fpf, rd, rn);
6991 return;
6992 case NEON_FSQRT_H:
6993 fsqrt(fpf, rd, rn);
6994 return;
6995 case NEON_FRSQRTE_H:
6996 frsqrte(fpf, rd, rn);
6997 return;
6998 case NEON_FRECPE_H:
6999 frecpe(fpf, rd, rn, fpcr_rounding);
7000 return;
7001 case NEON_FCMGT_H_zero:
7002 fcmp_zero(fpf, rd, rn, gt);
7003 return;
7004 case NEON_FCMGE_H_zero:
7005 fcmp_zero(fpf, rd, rn, ge);
7006 return;
7007 case NEON_FCMEQ_H_zero:
7008 fcmp_zero(fpf, rd, rn, eq);
7009 return;
7010 case NEON_FCMLE_H_zero:
7011 fcmp_zero(fpf, rd, rn, le);
7012 return;
7013 case NEON_FCMLT_H_zero:
7014 fcmp_zero(fpf, rd, rn, lt);
7015 return;
7016 default:
7017 VIXL_UNIMPLEMENTED();
7018 return;
7019 }
7020}
7021
7022
Alexandre Ramesd3832962016-07-04 15:03:43 +01007023void Simulator::VisitNEON3Same(const Instruction* instr) {
7024 NEONFormatDecoder nfd(instr);
7025 SimVRegister& rd = ReadVRegister(instr->GetRd());
7026 SimVRegister& rn = ReadVRegister(instr->GetRn());
7027 SimVRegister& rm = ReadVRegister(instr->GetRm());
7028
7029 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
7030 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7031 switch (instr->Mask(NEON3SameLogicalMask)) {
7032 case NEON_AND:
7033 and_(vf, rd, rn, rm);
7034 break;
7035 case NEON_ORR:
7036 orr(vf, rd, rn, rm);
7037 break;
7038 case NEON_ORN:
7039 orn(vf, rd, rn, rm);
7040 break;
7041 case NEON_EOR:
7042 eor(vf, rd, rn, rm);
7043 break;
7044 case NEON_BIC:
7045 bic(vf, rd, rn, rm);
7046 break;
7047 case NEON_BIF:
7048 bif(vf, rd, rn, rm);
7049 break;
7050 case NEON_BIT:
7051 bit(vf, rd, rn, rm);
7052 break;
7053 case NEON_BSL:
Martyn Capewellb1b95782020-10-23 15:59:49 +01007054 bsl(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007055 break;
7056 default:
7057 VIXL_UNIMPLEMENTED();
7058 }
7059 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7060 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7061 switch (instr->Mask(NEON3SameFPMask)) {
7062 case NEON_FADD:
7063 fadd(vf, rd, rn, rm);
7064 break;
7065 case NEON_FSUB:
7066 fsub(vf, rd, rn, rm);
7067 break;
7068 case NEON_FMUL:
7069 fmul(vf, rd, rn, rm);
7070 break;
7071 case NEON_FDIV:
7072 fdiv(vf, rd, rn, rm);
7073 break;
7074 case NEON_FMAX:
7075 fmax(vf, rd, rn, rm);
7076 break;
7077 case NEON_FMIN:
7078 fmin(vf, rd, rn, rm);
7079 break;
7080 case NEON_FMAXNM:
7081 fmaxnm(vf, rd, rn, rm);
7082 break;
7083 case NEON_FMINNM:
7084 fminnm(vf, rd, rn, rm);
7085 break;
7086 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007087 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007088 break;
7089 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08007090 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007091 break;
7092 case NEON_FMULX:
7093 fmulx(vf, rd, rn, rm);
7094 break;
7095 case NEON_FACGE:
7096 fabscmp(vf, rd, rn, rm, ge);
7097 break;
7098 case NEON_FACGT:
7099 fabscmp(vf, rd, rn, rm, gt);
7100 break;
7101 case NEON_FCMEQ:
7102 fcmp(vf, rd, rn, rm, eq);
7103 break;
7104 case NEON_FCMGE:
7105 fcmp(vf, rd, rn, rm, ge);
7106 break;
7107 case NEON_FCMGT:
7108 fcmp(vf, rd, rn, rm, gt);
7109 break;
7110 case NEON_FRECPS:
7111 frecps(vf, rd, rn, rm);
7112 break;
7113 case NEON_FRSQRTS:
7114 frsqrts(vf, rd, rn, rm);
7115 break;
7116 case NEON_FABD:
7117 fabd(vf, rd, rn, rm);
7118 break;
7119 case NEON_FADDP:
7120 faddp(vf, rd, rn, rm);
7121 break;
7122 case NEON_FMAXP:
7123 fmaxp(vf, rd, rn, rm);
7124 break;
7125 case NEON_FMAXNMP:
7126 fmaxnmp(vf, rd, rn, rm);
7127 break;
7128 case NEON_FMINP:
7129 fminp(vf, rd, rn, rm);
7130 break;
7131 case NEON_FMINNMP:
7132 fminnmp(vf, rd, rn, rm);
7133 break;
7134 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007135 // FMLAL{2} and FMLSL{2} have special-case encodings.
7136 switch (instr->Mask(NEON3SameFHMMask)) {
7137 case NEON_FMLAL:
7138 fmlal(vf, rd, rn, rm);
7139 break;
7140 case NEON_FMLAL2:
7141 fmlal2(vf, rd, rn, rm);
7142 break;
7143 case NEON_FMLSL:
7144 fmlsl(vf, rd, rn, rm);
7145 break;
7146 case NEON_FMLSL2:
7147 fmlsl2(vf, rd, rn, rm);
7148 break;
7149 default:
7150 VIXL_UNIMPLEMENTED();
7151 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007152 }
7153 } else {
7154 VectorFormat vf = nfd.GetVectorFormat();
7155 switch (instr->Mask(NEON3SameMask)) {
7156 case NEON_ADD:
7157 add(vf, rd, rn, rm);
7158 break;
7159 case NEON_ADDP:
7160 addp(vf, rd, rn, rm);
7161 break;
7162 case NEON_CMEQ:
7163 cmp(vf, rd, rn, rm, eq);
7164 break;
7165 case NEON_CMGE:
7166 cmp(vf, rd, rn, rm, ge);
7167 break;
7168 case NEON_CMGT:
7169 cmp(vf, rd, rn, rm, gt);
7170 break;
7171 case NEON_CMHI:
7172 cmp(vf, rd, rn, rm, hi);
7173 break;
7174 case NEON_CMHS:
7175 cmp(vf, rd, rn, rm, hs);
7176 break;
7177 case NEON_CMTST:
7178 cmptst(vf, rd, rn, rm);
7179 break;
7180 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01007181 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007182 break;
7183 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01007184 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007185 break;
7186 case NEON_MUL:
7187 mul(vf, rd, rn, rm);
7188 break;
7189 case NEON_PMUL:
7190 pmul(vf, rd, rn, rm);
7191 break;
7192 case NEON_SMAX:
7193 smax(vf, rd, rn, rm);
7194 break;
7195 case NEON_SMAXP:
7196 smaxp(vf, rd, rn, rm);
7197 break;
7198 case NEON_SMIN:
7199 smin(vf, rd, rn, rm);
7200 break;
7201 case NEON_SMINP:
7202 sminp(vf, rd, rn, rm);
7203 break;
7204 case NEON_SUB:
7205 sub(vf, rd, rn, rm);
7206 break;
7207 case NEON_UMAX:
7208 umax(vf, rd, rn, rm);
7209 break;
7210 case NEON_UMAXP:
7211 umaxp(vf, rd, rn, rm);
7212 break;
7213 case NEON_UMIN:
7214 umin(vf, rd, rn, rm);
7215 break;
7216 case NEON_UMINP:
7217 uminp(vf, rd, rn, rm);
7218 break;
7219 case NEON_SSHL:
7220 sshl(vf, rd, rn, rm);
7221 break;
7222 case NEON_USHL:
7223 ushl(vf, rd, rn, rm);
7224 break;
7225 case NEON_SABD:
7226 absdiff(vf, rd, rn, rm, true);
7227 break;
7228 case NEON_UABD:
7229 absdiff(vf, rd, rn, rm, false);
7230 break;
7231 case NEON_SABA:
7232 saba(vf, rd, rn, rm);
7233 break;
7234 case NEON_UABA:
7235 uaba(vf, rd, rn, rm);
7236 break;
7237 case NEON_UQADD:
7238 add(vf, rd, rn, rm).UnsignedSaturate(vf);
7239 break;
7240 case NEON_SQADD:
7241 add(vf, rd, rn, rm).SignedSaturate(vf);
7242 break;
7243 case NEON_UQSUB:
7244 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7245 break;
7246 case NEON_SQSUB:
7247 sub(vf, rd, rn, rm).SignedSaturate(vf);
7248 break;
7249 case NEON_SQDMULH:
7250 sqdmulh(vf, rd, rn, rm);
7251 break;
7252 case NEON_SQRDMULH:
7253 sqrdmulh(vf, rd, rn, rm);
7254 break;
7255 case NEON_UQSHL:
7256 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7257 break;
7258 case NEON_SQSHL:
7259 sshl(vf, rd, rn, rm).SignedSaturate(vf);
7260 break;
7261 case NEON_URSHL:
7262 ushl(vf, rd, rn, rm).Round(vf);
7263 break;
7264 case NEON_SRSHL:
7265 sshl(vf, rd, rn, rm).Round(vf);
7266 break;
7267 case NEON_UQRSHL:
7268 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7269 break;
7270 case NEON_SQRSHL:
7271 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7272 break;
7273 case NEON_UHADD:
7274 add(vf, rd, rn, rm).Uhalve(vf);
7275 break;
7276 case NEON_URHADD:
7277 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7278 break;
7279 case NEON_SHADD:
7280 add(vf, rd, rn, rm).Halve(vf);
7281 break;
7282 case NEON_SRHADD:
7283 add(vf, rd, rn, rm).Halve(vf).Round(vf);
7284 break;
7285 case NEON_UHSUB:
7286 sub(vf, rd, rn, rm).Uhalve(vf);
7287 break;
7288 case NEON_SHSUB:
7289 sub(vf, rd, rn, rm).Halve(vf);
7290 break;
7291 default:
7292 VIXL_UNIMPLEMENTED();
7293 }
7294 }
7295}
7296
7297
Jacob Bramleyca789742018-09-13 14:25:46 +01007298void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7299 NEONFormatDecoder nfd(instr);
7300 SimVRegister& rd = ReadVRegister(instr->GetRd());
7301 SimVRegister& rn = ReadVRegister(instr->GetRn());
7302 SimVRegister& rm = ReadVRegister(instr->GetRm());
7303
7304 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7305 switch (instr->Mask(NEON3SameFP16Mask)) {
7306#define SIM_FUNC(A, B) \
7307 case NEON_##A##_H: \
7308 B(vf, rd, rn, rm); \
7309 break;
7310 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007311 SIM_FUNC(FADD, fadd);
7312 SIM_FUNC(FMULX, fmulx);
7313 SIM_FUNC(FMAX, fmax);
7314 SIM_FUNC(FRECPS, frecps);
7315 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01007316 SIM_FUNC(FSUB, fsub);
7317 SIM_FUNC(FMIN, fmin);
7318 SIM_FUNC(FRSQRTS, frsqrts);
7319 SIM_FUNC(FMAXNMP, fmaxnmp);
7320 SIM_FUNC(FADDP, faddp);
7321 SIM_FUNC(FMUL, fmul);
7322 SIM_FUNC(FMAXP, fmaxp);
7323 SIM_FUNC(FDIV, fdiv);
7324 SIM_FUNC(FMINNMP, fminnmp);
7325 SIM_FUNC(FABD, fabd);
7326 SIM_FUNC(FMINP, fminp);
7327#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08007328 case NEON_FMLA_H:
7329 fmla(vf, rd, rd, rn, rm);
7330 break;
7331 case NEON_FMLS_H:
7332 fmls(vf, rd, rd, rn, rm);
7333 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007334 case NEON_FCMEQ_H:
7335 fcmp(vf, rd, rn, rm, eq);
7336 break;
7337 case NEON_FCMGE_H:
7338 fcmp(vf, rd, rn, rm, ge);
7339 break;
7340 case NEON_FACGE_H:
7341 fabscmp(vf, rd, rn, rm, ge);
7342 break;
7343 case NEON_FCMGT_H:
7344 fcmp(vf, rd, rn, rm, gt);
7345 break;
7346 case NEON_FACGT_H:
7347 fabscmp(vf, rd, rn, rm, gt);
7348 break;
7349 default:
7350 VIXL_UNIMPLEMENTED();
7351 break;
7352 }
7353}
7354
Carey Williams2809e6c2018-03-13 12:24:16 +00007355void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7356 NEONFormatDecoder nfd(instr);
7357 SimVRegister& rd = ReadVRegister(instr->GetRd());
7358 SimVRegister& rn = ReadVRegister(instr->GetRn());
7359 SimVRegister& rm = ReadVRegister(instr->GetRm());
7360 int rot = 0;
7361 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01007362 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
7363 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01007364 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01007365 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
7366 rot = instr->GetImmRotFcadd();
7367 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01007368 } else {
7369 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01007370 case NEON_SDOT:
7371 sdot(vf, rd, rn, rm);
7372 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007373 case NEON_SQRDMLAH:
7374 sqrdmlah(vf, rd, rn, rm);
7375 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007376 case NEON_UDOT:
7377 udot(vf, rd, rn, rm);
7378 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007379 case NEON_SQRDMLSH:
7380 sqrdmlsh(vf, rd, rn, rm);
7381 break;
7382 default:
7383 VIXL_UNIMPLEMENTED();
7384 break;
7385 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007386 }
7387}
7388
7389
Alexandre Ramesd3832962016-07-04 15:03:43 +01007390void Simulator::VisitNEON3Different(const Instruction* instr) {
7391 NEONFormatDecoder nfd(instr);
7392 VectorFormat vf = nfd.GetVectorFormat();
7393 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7394
7395 SimVRegister& rd = ReadVRegister(instr->GetRd());
7396 SimVRegister& rn = ReadVRegister(instr->GetRn());
7397 SimVRegister& rm = ReadVRegister(instr->GetRm());
7398
7399 switch (instr->Mask(NEON3DifferentMask)) {
7400 case NEON_PMULL:
7401 pmull(vf_l, rd, rn, rm);
7402 break;
7403 case NEON_PMULL2:
7404 pmull2(vf_l, rd, rn, rm);
7405 break;
7406 case NEON_UADDL:
7407 uaddl(vf_l, rd, rn, rm);
7408 break;
7409 case NEON_UADDL2:
7410 uaddl2(vf_l, rd, rn, rm);
7411 break;
7412 case NEON_SADDL:
7413 saddl(vf_l, rd, rn, rm);
7414 break;
7415 case NEON_SADDL2:
7416 saddl2(vf_l, rd, rn, rm);
7417 break;
7418 case NEON_USUBL:
7419 usubl(vf_l, rd, rn, rm);
7420 break;
7421 case NEON_USUBL2:
7422 usubl2(vf_l, rd, rn, rm);
7423 break;
7424 case NEON_SSUBL:
7425 ssubl(vf_l, rd, rn, rm);
7426 break;
7427 case NEON_SSUBL2:
7428 ssubl2(vf_l, rd, rn, rm);
7429 break;
7430 case NEON_SABAL:
7431 sabal(vf_l, rd, rn, rm);
7432 break;
7433 case NEON_SABAL2:
7434 sabal2(vf_l, rd, rn, rm);
7435 break;
7436 case NEON_UABAL:
7437 uabal(vf_l, rd, rn, rm);
7438 break;
7439 case NEON_UABAL2:
7440 uabal2(vf_l, rd, rn, rm);
7441 break;
7442 case NEON_SABDL:
7443 sabdl(vf_l, rd, rn, rm);
7444 break;
7445 case NEON_SABDL2:
7446 sabdl2(vf_l, rd, rn, rm);
7447 break;
7448 case NEON_UABDL:
7449 uabdl(vf_l, rd, rn, rm);
7450 break;
7451 case NEON_UABDL2:
7452 uabdl2(vf_l, rd, rn, rm);
7453 break;
7454 case NEON_SMLAL:
7455 smlal(vf_l, rd, rn, rm);
7456 break;
7457 case NEON_SMLAL2:
7458 smlal2(vf_l, rd, rn, rm);
7459 break;
7460 case NEON_UMLAL:
7461 umlal(vf_l, rd, rn, rm);
7462 break;
7463 case NEON_UMLAL2:
7464 umlal2(vf_l, rd, rn, rm);
7465 break;
7466 case NEON_SMLSL:
7467 smlsl(vf_l, rd, rn, rm);
7468 break;
7469 case NEON_SMLSL2:
7470 smlsl2(vf_l, rd, rn, rm);
7471 break;
7472 case NEON_UMLSL:
7473 umlsl(vf_l, rd, rn, rm);
7474 break;
7475 case NEON_UMLSL2:
7476 umlsl2(vf_l, rd, rn, rm);
7477 break;
7478 case NEON_SMULL:
7479 smull(vf_l, rd, rn, rm);
7480 break;
7481 case NEON_SMULL2:
7482 smull2(vf_l, rd, rn, rm);
7483 break;
7484 case NEON_UMULL:
7485 umull(vf_l, rd, rn, rm);
7486 break;
7487 case NEON_UMULL2:
7488 umull2(vf_l, rd, rn, rm);
7489 break;
7490 case NEON_SQDMLAL:
7491 sqdmlal(vf_l, rd, rn, rm);
7492 break;
7493 case NEON_SQDMLAL2:
7494 sqdmlal2(vf_l, rd, rn, rm);
7495 break;
7496 case NEON_SQDMLSL:
7497 sqdmlsl(vf_l, rd, rn, rm);
7498 break;
7499 case NEON_SQDMLSL2:
7500 sqdmlsl2(vf_l, rd, rn, rm);
7501 break;
7502 case NEON_SQDMULL:
7503 sqdmull(vf_l, rd, rn, rm);
7504 break;
7505 case NEON_SQDMULL2:
7506 sqdmull2(vf_l, rd, rn, rm);
7507 break;
7508 case NEON_UADDW:
7509 uaddw(vf_l, rd, rn, rm);
7510 break;
7511 case NEON_UADDW2:
7512 uaddw2(vf_l, rd, rn, rm);
7513 break;
7514 case NEON_SADDW:
7515 saddw(vf_l, rd, rn, rm);
7516 break;
7517 case NEON_SADDW2:
7518 saddw2(vf_l, rd, rn, rm);
7519 break;
7520 case NEON_USUBW:
7521 usubw(vf_l, rd, rn, rm);
7522 break;
7523 case NEON_USUBW2:
7524 usubw2(vf_l, rd, rn, rm);
7525 break;
7526 case NEON_SSUBW:
7527 ssubw(vf_l, rd, rn, rm);
7528 break;
7529 case NEON_SSUBW2:
7530 ssubw2(vf_l, rd, rn, rm);
7531 break;
7532 case NEON_ADDHN:
7533 addhn(vf, rd, rn, rm);
7534 break;
7535 case NEON_ADDHN2:
7536 addhn2(vf, rd, rn, rm);
7537 break;
7538 case NEON_RADDHN:
7539 raddhn(vf, rd, rn, rm);
7540 break;
7541 case NEON_RADDHN2:
7542 raddhn2(vf, rd, rn, rm);
7543 break;
7544 case NEON_SUBHN:
7545 subhn(vf, rd, rn, rm);
7546 break;
7547 case NEON_SUBHN2:
7548 subhn2(vf, rd, rn, rm);
7549 break;
7550 case NEON_RSUBHN:
7551 rsubhn(vf, rd, rn, rm);
7552 break;
7553 case NEON_RSUBHN2:
7554 rsubhn2(vf, rd, rn, rm);
7555 break;
7556 default:
7557 VIXL_UNIMPLEMENTED();
7558 }
7559}
7560
7561
7562void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7563 NEONFormatDecoder nfd(instr);
7564
Jacob Bramleyca789742018-09-13 14:25:46 +01007565 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7566
Alexandre Ramesd3832962016-07-04 15:03:43 +01007567 SimVRegister& rd = ReadVRegister(instr->GetRd());
7568 SimVRegister& rn = ReadVRegister(instr->GetRn());
7569
Jacob Bramleyca789742018-09-13 14:25:46 +01007570 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7571 VectorFormat vf = nfd.GetVectorFormat(&map_half);
7572 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7573 case NEON_FMAXV_H:
7574 fmaxv(vf, rd, rn);
7575 break;
7576 case NEON_FMINV_H:
7577 fminv(vf, rd, rn);
7578 break;
7579 case NEON_FMAXNMV_H:
7580 fmaxnmv(vf, rd, rn);
7581 break;
7582 case NEON_FMINNMV_H:
7583 fminnmv(vf, rd, rn);
7584 break;
7585 default:
7586 VIXL_UNIMPLEMENTED();
7587 }
7588 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7589 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01007590 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7591
7592 switch (instr->Mask(NEONAcrossLanesFPMask)) {
7593 case NEON_FMAXV:
7594 fmaxv(vf, rd, rn);
7595 break;
7596 case NEON_FMINV:
7597 fminv(vf, rd, rn);
7598 break;
7599 case NEON_FMAXNMV:
7600 fmaxnmv(vf, rd, rn);
7601 break;
7602 case NEON_FMINNMV:
7603 fminnmv(vf, rd, rn);
7604 break;
7605 default:
7606 VIXL_UNIMPLEMENTED();
7607 }
7608 } else {
7609 VectorFormat vf = nfd.GetVectorFormat();
7610
7611 switch (instr->Mask(NEONAcrossLanesMask)) {
7612 case NEON_ADDV:
7613 addv(vf, rd, rn);
7614 break;
7615 case NEON_SMAXV:
7616 smaxv(vf, rd, rn);
7617 break;
7618 case NEON_SMINV:
7619 sminv(vf, rd, rn);
7620 break;
7621 case NEON_UMAXV:
7622 umaxv(vf, rd, rn);
7623 break;
7624 case NEON_UMINV:
7625 uminv(vf, rd, rn);
7626 break;
7627 case NEON_SADDLV:
7628 saddlv(vf, rd, rn);
7629 break;
7630 case NEON_UADDLV:
7631 uaddlv(vf, rd, rn);
7632 break;
7633 default:
7634 VIXL_UNIMPLEMENTED();
7635 }
7636 }
7637}
7638
7639
7640void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7641 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01007642 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007643 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01007644 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007645 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7646
7647 SimVRegister& rd = ReadVRegister(instr->GetRd());
7648 SimVRegister& rn = ReadVRegister(instr->GetRn());
7649
7650 ByElementOp Op = NULL;
7651
7652 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007653 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007654 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007655 int index_hlm = (index << 1) | instr->GetNEONM();
7656
7657 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
7658 // These are oddballs and are best handled as special cases.
7659 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
7660 // - The index is always H:L:M.
7661 case NEON_FMLAL_H_byelement:
7662 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7663 return;
7664 case NEON_FMLAL2_H_byelement:
7665 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7666 return;
7667 case NEON_FMLSL_H_byelement:
7668 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7669 return;
7670 case NEON_FMLSL2_H_byelement:
7671 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
7672 return;
7673 }
7674
Alexandre Ramesd3832962016-07-04 15:03:43 +01007675 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007676 rm_reg = rm_low_reg;
7677 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007678 }
7679
7680 switch (instr->Mask(NEONByIndexedElementMask)) {
7681 case NEON_MUL_byelement:
7682 Op = &Simulator::mul;
7683 vf = vf_r;
7684 break;
7685 case NEON_MLA_byelement:
7686 Op = &Simulator::mla;
7687 vf = vf_r;
7688 break;
7689 case NEON_MLS_byelement:
7690 Op = &Simulator::mls;
7691 vf = vf_r;
7692 break;
7693 case NEON_SQDMULH_byelement:
7694 Op = &Simulator::sqdmulh;
7695 vf = vf_r;
7696 break;
7697 case NEON_SQRDMULH_byelement:
7698 Op = &Simulator::sqrdmulh;
7699 vf = vf_r;
7700 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007701 case NEON_SDOT_byelement:
7702 Op = &Simulator::sdot;
7703 vf = vf_r;
7704 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007705 case NEON_SQRDMLAH_byelement:
7706 Op = &Simulator::sqrdmlah;
7707 vf = vf_r;
7708 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01007709 case NEON_UDOT_byelement:
7710 Op = &Simulator::udot;
7711 vf = vf_r;
7712 break;
Alexander Gilday43785642018-04-04 13:42:33 +01007713 case NEON_SQRDMLSH_byelement:
7714 Op = &Simulator::sqrdmlsh;
7715 vf = vf_r;
7716 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007717 case NEON_SMULL_byelement:
7718 if (instr->Mask(NEON_Q)) {
7719 Op = &Simulator::smull2;
7720 } else {
7721 Op = &Simulator::smull;
7722 }
7723 break;
7724 case NEON_UMULL_byelement:
7725 if (instr->Mask(NEON_Q)) {
7726 Op = &Simulator::umull2;
7727 } else {
7728 Op = &Simulator::umull;
7729 }
7730 break;
7731 case NEON_SMLAL_byelement:
7732 if (instr->Mask(NEON_Q)) {
7733 Op = &Simulator::smlal2;
7734 } else {
7735 Op = &Simulator::smlal;
7736 }
7737 break;
7738 case NEON_UMLAL_byelement:
7739 if (instr->Mask(NEON_Q)) {
7740 Op = &Simulator::umlal2;
7741 } else {
7742 Op = &Simulator::umlal;
7743 }
7744 break;
7745 case NEON_SMLSL_byelement:
7746 if (instr->Mask(NEON_Q)) {
7747 Op = &Simulator::smlsl2;
7748 } else {
7749 Op = &Simulator::smlsl;
7750 }
7751 break;
7752 case NEON_UMLSL_byelement:
7753 if (instr->Mask(NEON_Q)) {
7754 Op = &Simulator::umlsl2;
7755 } else {
7756 Op = &Simulator::umlsl;
7757 }
7758 break;
7759 case NEON_SQDMULL_byelement:
7760 if (instr->Mask(NEON_Q)) {
7761 Op = &Simulator::sqdmull2;
7762 } else {
7763 Op = &Simulator::sqdmull;
7764 }
7765 break;
7766 case NEON_SQDMLAL_byelement:
7767 if (instr->Mask(NEON_Q)) {
7768 Op = &Simulator::sqdmlal2;
7769 } else {
7770 Op = &Simulator::sqdmlal;
7771 }
7772 break;
7773 case NEON_SQDMLSL_byelement:
7774 if (instr->Mask(NEON_Q)) {
7775 Op = &Simulator::sqdmlsl2;
7776 } else {
7777 Op = &Simulator::sqdmlsl;
7778 }
7779 break;
7780 default:
7781 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01007782 if (instr->GetFPType() == 0) {
7783 rm_reg &= 0xf;
7784 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7785 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007786 index = (index << 1) | instr->GetNEONL();
7787 }
7788
7789 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7790
7791 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01007792 case NEON_FMUL_H_byelement:
7793 vf = vf_half;
7794 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007795 case NEON_FMUL_byelement:
7796 Op = &Simulator::fmul;
7797 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007798 case NEON_FMLA_H_byelement:
7799 vf = vf_half;
7800 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007801 case NEON_FMLA_byelement:
7802 Op = &Simulator::fmla;
7803 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007804 case NEON_FMLS_H_byelement:
7805 vf = vf_half;
7806 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007807 case NEON_FMLS_byelement:
7808 Op = &Simulator::fmls;
7809 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01007810 case NEON_FMULX_H_byelement:
7811 vf = vf_half;
7812 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01007813 case NEON_FMULX_byelement:
7814 Op = &Simulator::fmulx;
7815 break;
7816 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007817 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00007818 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007819 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00007820 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01007821 }
Carey Williams2809e6c2018-03-13 12:24:16 +00007822 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
7823 case NEON_FCMLA_byelement:
7824 vf = vf_r;
7825 fcmla(vf,
7826 rd,
7827 rn,
7828 ReadVRegister(instr->GetRm()),
7829 index,
7830 instr->GetImmRotFcmlaSca());
7831 return;
7832 default:
7833 VIXL_UNIMPLEMENTED();
7834 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007835 }
7836 }
7837
7838 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
7839}
7840
7841
7842void Simulator::VisitNEONCopy(const Instruction* instr) {
7843 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7844 VectorFormat vf = nfd.GetVectorFormat();
7845
7846 SimVRegister& rd = ReadVRegister(instr->GetRd());
7847 SimVRegister& rn = ReadVRegister(instr->GetRn());
7848 int imm5 = instr->GetImmNEON5();
7849 int tz = CountTrailingZeros(imm5, 32);
7850 int reg_index = imm5 >> (tz + 1);
7851
7852 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7853 int imm4 = instr->GetImmNEON4();
7854 int rn_index = imm4 >> tz;
7855 ins_element(vf, rd, reg_index, rn, rn_index);
7856 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7857 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7858 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7859 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7860 value &= MaxUintFromFormat(vf);
7861 WriteXRegister(instr->GetRd(), value);
7862 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7863 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7864 if (instr->GetNEONQ()) {
7865 WriteXRegister(instr->GetRd(), value);
7866 } else {
7867 WriteWRegister(instr->GetRd(), (int32_t)value);
7868 }
7869 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7870 dup_element(vf, rd, rn, reg_index);
7871 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7872 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7873 } else {
7874 VIXL_UNIMPLEMENTED();
7875 }
7876}
7877
7878
7879void Simulator::VisitNEONExtract(const Instruction* instr) {
7880 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7881 VectorFormat vf = nfd.GetVectorFormat();
7882 SimVRegister& rd = ReadVRegister(instr->GetRd());
7883 SimVRegister& rn = ReadVRegister(instr->GetRn());
7884 SimVRegister& rm = ReadVRegister(instr->GetRm());
7885 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7886 int index = instr->GetImmNEONExt();
7887 ext(vf, rd, rn, rm, index);
7888 } else {
7889 VIXL_UNIMPLEMENTED();
7890 }
7891}
7892
7893
7894void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7895 AddrMode addr_mode) {
7896 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7897 VectorFormat vf = nfd.GetVectorFormat();
7898
7899 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7900 int reg_size = RegisterSizeInBytesFromFormat(vf);
7901
7902 int reg[4];
7903 uint64_t addr[4];
7904 for (int i = 0; i < 4; i++) {
7905 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7906 addr[i] = addr_base + (i * reg_size);
7907 }
Jacob Bramley423e5422019-11-13 19:15:55 +00007908 int struct_parts = 1;
7909 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007910 bool log_read = true;
7911
Martyn Capewell32009e32016-10-27 11:00:37 +01007912 // Bit 23 determines whether this is an offset or post-index addressing mode.
7913 // In offset mode, bits 20 to 16 should be zero; these bits encode the
7914 // register or immediate in post-index mode.
7915 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007916 VIXL_UNREACHABLE();
7917 }
7918
7919 // We use the PostIndex mask here, as it works in this case for both Offset
7920 // and PostIndex addressing.
7921 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7922 case NEON_LD1_4v:
7923 case NEON_LD1_4v_post:
7924 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007925 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007926 VIXL_FALLTHROUGH();
7927 case NEON_LD1_3v:
7928 case NEON_LD1_3v_post:
7929 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007930 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007931 VIXL_FALLTHROUGH();
7932 case NEON_LD1_2v:
7933 case NEON_LD1_2v_post:
7934 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007935 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007936 VIXL_FALLTHROUGH();
7937 case NEON_LD1_1v:
7938 case NEON_LD1_1v_post:
7939 ld1(vf, ReadVRegister(reg[0]), addr[0]);
7940 break;
7941 case NEON_ST1_4v:
7942 case NEON_ST1_4v_post:
7943 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007944 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007945 VIXL_FALLTHROUGH();
7946 case NEON_ST1_3v:
7947 case NEON_ST1_3v_post:
7948 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007949 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007950 VIXL_FALLTHROUGH();
7951 case NEON_ST1_2v:
7952 case NEON_ST1_2v_post:
7953 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007954 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007955 VIXL_FALLTHROUGH();
7956 case NEON_ST1_1v:
7957 case NEON_ST1_1v_post:
7958 st1(vf, ReadVRegister(reg[0]), addr[0]);
7959 log_read = false;
7960 break;
7961 case NEON_LD2_post:
7962 case NEON_LD2:
7963 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007964 struct_parts = 2;
7965 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007966 break;
7967 case NEON_ST2:
7968 case NEON_ST2_post:
7969 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007970 struct_parts = 2;
7971 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01007972 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007973 break;
7974 case NEON_LD3_post:
7975 case NEON_LD3:
7976 ld3(vf,
7977 ReadVRegister(reg[0]),
7978 ReadVRegister(reg[1]),
7979 ReadVRegister(reg[2]),
7980 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007981 struct_parts = 3;
7982 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007983 break;
7984 case NEON_ST3:
7985 case NEON_ST3_post:
7986 st3(vf,
7987 ReadVRegister(reg[0]),
7988 ReadVRegister(reg[1]),
7989 ReadVRegister(reg[2]),
7990 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00007991 struct_parts = 3;
7992 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01007993 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01007994 break;
7995 case NEON_ST4:
7996 case NEON_ST4_post:
7997 st4(vf,
7998 ReadVRegister(reg[0]),
7999 ReadVRegister(reg[1]),
8000 ReadVRegister(reg[2]),
8001 ReadVRegister(reg[3]),
8002 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008003 struct_parts = 4;
8004 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01008005 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008006 break;
8007 case NEON_LD4_post:
8008 case NEON_LD4:
8009 ld4(vf,
8010 ReadVRegister(reg[0]),
8011 ReadVRegister(reg[1]),
8012 ReadVRegister(reg[2]),
8013 ReadVRegister(reg[3]),
8014 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00008015 struct_parts = 4;
8016 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008017 break;
8018 default:
8019 VIXL_UNIMPLEMENTED();
8020 }
8021
Jacob Bramley7eb3e212019-11-22 17:28:05 +00008022 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00008023 if (do_trace) {
8024 PrintRegisterFormat print_format =
8025 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8026 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008027 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00008028 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01008029 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00008030 op = "->";
8031 // Stores don't represent a change to the source register's value, so only
8032 // print the relevant part of the value.
8033 print_format = GetPrintRegPartial(print_format);
8034 }
8035
8036 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
8037 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
8038 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
8039 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008040 }
8041 }
8042
8043 if (addr_mode == PostIndex) {
8044 int rm = instr->GetRm();
8045 // The immediate post index addressing mode is indicated by rm = 31.
8046 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00008047 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01008048 : ReadXRegister(rm);
8049 WriteXRegister(instr->GetRn(), addr_base);
8050 } else {
8051 VIXL_ASSERT(addr_mode == Offset);
8052 }
8053}
8054
8055
8056void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8057 NEONLoadStoreMultiStructHelper(instr, Offset);
8058}
8059
8060
8061void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8062 const Instruction* instr) {
8063 NEONLoadStoreMultiStructHelper(instr, PostIndex);
8064}
8065
8066
8067void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8068 AddrMode addr_mode) {
8069 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8070 int rt = instr->GetRt();
8071
Martyn Capewell32009e32016-10-27 11:00:37 +01008072 // Bit 23 determines whether this is an offset or post-index addressing mode.
8073 // In offset mode, bits 20 to 16 should be zero; these bits encode the
8074 // register or immediate in post-index mode.
8075 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008076 VIXL_UNREACHABLE();
8077 }
8078
8079 // We use the PostIndex mask here, as it works in this case for both Offset
8080 // and PostIndex addressing.
8081 bool do_load = false;
8082
Jacob Bramley423e5422019-11-13 19:15:55 +00008083 bool replicating = false;
8084
Alexandre Ramesd3832962016-07-04 15:03:43 +01008085 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8086 VectorFormat vf_t = nfd.GetVectorFormat();
8087
8088 VectorFormat vf = kFormat16B;
8089 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8090 case NEON_LD1_b:
8091 case NEON_LD1_b_post:
8092 case NEON_LD2_b:
8093 case NEON_LD2_b_post:
8094 case NEON_LD3_b:
8095 case NEON_LD3_b_post:
8096 case NEON_LD4_b:
8097 case NEON_LD4_b_post:
8098 do_load = true;
8099 VIXL_FALLTHROUGH();
8100 case NEON_ST1_b:
8101 case NEON_ST1_b_post:
8102 case NEON_ST2_b:
8103 case NEON_ST2_b_post:
8104 case NEON_ST3_b:
8105 case NEON_ST3_b_post:
8106 case NEON_ST4_b:
8107 case NEON_ST4_b_post:
8108 break;
8109
8110 case NEON_LD1_h:
8111 case NEON_LD1_h_post:
8112 case NEON_LD2_h:
8113 case NEON_LD2_h_post:
8114 case NEON_LD3_h:
8115 case NEON_LD3_h_post:
8116 case NEON_LD4_h:
8117 case NEON_LD4_h_post:
8118 do_load = true;
8119 VIXL_FALLTHROUGH();
8120 case NEON_ST1_h:
8121 case NEON_ST1_h_post:
8122 case NEON_ST2_h:
8123 case NEON_ST2_h_post:
8124 case NEON_ST3_h:
8125 case NEON_ST3_h_post:
8126 case NEON_ST4_h:
8127 case NEON_ST4_h_post:
8128 vf = kFormat8H;
8129 break;
8130 case NEON_LD1_s:
8131 case NEON_LD1_s_post:
8132 case NEON_LD2_s:
8133 case NEON_LD2_s_post:
8134 case NEON_LD3_s:
8135 case NEON_LD3_s_post:
8136 case NEON_LD4_s:
8137 case NEON_LD4_s_post:
8138 do_load = true;
8139 VIXL_FALLTHROUGH();
8140 case NEON_ST1_s:
8141 case NEON_ST1_s_post:
8142 case NEON_ST2_s:
8143 case NEON_ST2_s_post:
8144 case NEON_ST3_s:
8145 case NEON_ST3_s_post:
8146 case NEON_ST4_s:
8147 case NEON_ST4_s_post: {
8148 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8149 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8150 NEON_LD1_d_post);
8151 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8152 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8153 NEON_ST1_d_post);
8154 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8155 break;
8156 }
8157
8158 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008159 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008160 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008161 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008162 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008163 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008164 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00008165 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008166 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008167 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00008168 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008169 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00008170
Alexandre Ramesd3832962016-07-04 15:03:43 +01008171 default:
8172 VIXL_UNIMPLEMENTED();
8173 }
8174
Alexandre Ramesd3832962016-07-04 15:03:43 +01008175 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8176 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00008177 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008178 int rt2 = (rt + 1) % kNumberOfVRegisters;
8179 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8180 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8181 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8182 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00008183 reg_count = 1;
8184 if (replicating) {
8185 VIXL_ASSERT(do_load);
8186 ld1r(vf, ReadVRegister(rt), addr);
8187 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008188 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008189 } else {
8190 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008191 }
8192 break;
8193 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00008194 reg_count = 2;
8195 if (replicating) {
8196 VIXL_ASSERT(do_load);
8197 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8198 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008199 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008200 } else {
8201 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008202 }
8203 break;
8204 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00008205 reg_count = 3;
8206 if (replicating) {
8207 VIXL_ASSERT(do_load);
8208 ld3r(vf,
8209 ReadVRegister(rt),
8210 ReadVRegister(rt2),
8211 ReadVRegister(rt3),
8212 addr);
8213 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008214 ld3(vf,
8215 ReadVRegister(rt),
8216 ReadVRegister(rt2),
8217 ReadVRegister(rt3),
8218 lane,
8219 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008220 } else {
8221 st3(vf,
8222 ReadVRegister(rt),
8223 ReadVRegister(rt2),
8224 ReadVRegister(rt3),
8225 lane,
8226 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008227 }
8228 break;
8229 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00008230 reg_count = 4;
8231 if (replicating) {
8232 VIXL_ASSERT(do_load);
8233 ld4r(vf,
8234 ReadVRegister(rt),
8235 ReadVRegister(rt2),
8236 ReadVRegister(rt3),
8237 ReadVRegister(rt4),
8238 addr);
8239 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008240 ld4(vf,
8241 ReadVRegister(rt),
8242 ReadVRegister(rt2),
8243 ReadVRegister(rt3),
8244 ReadVRegister(rt4),
8245 lane,
8246 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008247 } else {
8248 st4(vf,
8249 ReadVRegister(rt),
8250 ReadVRegister(rt2),
8251 ReadVRegister(rt3),
8252 ReadVRegister(rt4),
8253 lane,
8254 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008255 }
8256 break;
8257 default:
8258 VIXL_UNIMPLEMENTED();
8259 }
8260
Jacob Bramley423e5422019-11-13 19:15:55 +00008261 // Trace registers and/or memory writes.
8262 PrintRegisterFormat print_format =
8263 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8264 if (do_load) {
8265 if (ShouldTraceVRegs()) {
8266 if (replicating) {
8267 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8268 } else {
8269 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8270 }
8271 }
8272 } else {
8273 if (ShouldTraceWrites()) {
8274 // Stores don't represent a change to the source register's value, so only
8275 // print the relevant part of the value.
8276 print_format = GetPrintRegPartial(print_format);
8277 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8278 }
8279 }
8280
Alexandre Ramesd3832962016-07-04 15:03:43 +01008281 if (addr_mode == PostIndex) {
8282 int rm = instr->GetRm();
8283 int lane_size = LaneSizeInBytesFromFormat(vf);
8284 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00008285 addr + ((rm == 31) ? (reg_count * lane_size)
8286 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008287 }
8288}
8289
8290
8291void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8292 NEONLoadStoreSingleStructHelper(instr, Offset);
8293}
8294
8295
8296void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8297 const Instruction* instr) {
8298 NEONLoadStoreSingleStructHelper(instr, PostIndex);
8299}
8300
8301
8302void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8303 SimVRegister& rd = ReadVRegister(instr->GetRd());
8304 int cmode = instr->GetNEONCmode();
8305 int cmode_3_1 = (cmode >> 1) & 7;
8306 int cmode_3 = (cmode >> 3) & 1;
8307 int cmode_2 = (cmode >> 2) & 1;
8308 int cmode_1 = (cmode >> 1) & 1;
8309 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01008310 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008311 int q = instr->GetNEONQ();
8312 int op_bit = instr->GetNEONModImmOp();
8313 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01008314 // Find the format and immediate value
8315 uint64_t imm = 0;
8316 VectorFormat vform = kFormatUndefined;
8317 switch (cmode_3_1) {
8318 case 0x0:
8319 case 0x1:
8320 case 0x2:
8321 case 0x3:
8322 vform = (q == 1) ? kFormat4S : kFormat2S;
8323 imm = imm8 << (8 * cmode_3_1);
8324 break;
8325 case 0x4:
8326 case 0x5:
8327 vform = (q == 1) ? kFormat8H : kFormat4H;
8328 imm = imm8 << (8 * cmode_1);
8329 break;
8330 case 0x6:
8331 vform = (q == 1) ? kFormat4S : kFormat2S;
8332 if (cmode_0 == 0) {
8333 imm = imm8 << 8 | 0x000000ff;
8334 } else {
8335 imm = imm8 << 16 | 0x0000ffff;
8336 }
8337 break;
8338 case 0x7:
8339 if (cmode_0 == 0 && op_bit == 0) {
8340 vform = q ? kFormat16B : kFormat8B;
8341 imm = imm8;
8342 } else if (cmode_0 == 0 && op_bit == 1) {
8343 vform = q ? kFormat2D : kFormat1D;
8344 imm = 0;
8345 for (int i = 0; i < 8; ++i) {
8346 if (imm8 & (1 << i)) {
8347 imm |= (UINT64_C(0xff) << (8 * i));
8348 }
8349 }
8350 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01008351 if (half_enc == 1) {
8352 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01008353 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01008354 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008355 vform = q ? kFormat4S : kFormat2S;
8356 imm = FloatToRawbits(instr->GetImmNEONFP32());
8357 } else if (q == 1) {
8358 vform = kFormat2D;
8359 imm = DoubleToRawbits(instr->GetImmNEONFP64());
8360 } else {
8361 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8362 VisitUnallocated(instr);
8363 }
8364 }
8365 break;
8366 default:
8367 VIXL_UNREACHABLE();
8368 break;
8369 }
8370
8371 // Find the operation
8372 NEONModifiedImmediateOp op;
8373 if (cmode_3 == 0) {
8374 if (cmode_0 == 0) {
8375 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8376 } else { // cmode<0> == '1'
8377 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8378 }
8379 } else { // cmode<3> == '1'
8380 if (cmode_2 == 0) {
8381 if (cmode_0 == 0) {
8382 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8383 } else { // cmode<0> == '1'
8384 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8385 }
8386 } else { // cmode<2> == '1'
8387 if (cmode_1 == 0) {
8388 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8389 } else { // cmode<1> == '1'
8390 if (cmode_0 == 0) {
8391 op = NEONModifiedImmediate_MOVI;
8392 } else { // cmode<0> == '1'
8393 op = NEONModifiedImmediate_MOVI;
8394 }
8395 }
8396 }
8397 }
8398
8399 // Call the logic function
8400 if (op == NEONModifiedImmediate_ORR) {
8401 orr(vform, rd, rd, imm);
8402 } else if (op == NEONModifiedImmediate_BIC) {
8403 bic(vform, rd, rd, imm);
8404 } else if (op == NEONModifiedImmediate_MOVI) {
8405 movi(vform, rd, imm);
8406 } else if (op == NEONModifiedImmediate_MVNI) {
8407 mvni(vform, rd, imm);
8408 } else {
8409 VisitUnimplemented(instr);
8410 }
8411}
8412
8413
8414void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8415 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8416 VectorFormat vf = nfd.GetVectorFormat();
8417
8418 SimVRegister& rd = ReadVRegister(instr->GetRd());
8419 SimVRegister& rn = ReadVRegister(instr->GetRn());
8420
8421 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8422 // These instructions all use a two bit size field, except NOT and RBIT,
8423 // which use the field to encode the operation.
8424 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8425 case NEON_CMEQ_zero_scalar:
8426 cmp(vf, rd, rn, 0, eq);
8427 break;
8428 case NEON_CMGE_zero_scalar:
8429 cmp(vf, rd, rn, 0, ge);
8430 break;
8431 case NEON_CMGT_zero_scalar:
8432 cmp(vf, rd, rn, 0, gt);
8433 break;
8434 case NEON_CMLT_zero_scalar:
8435 cmp(vf, rd, rn, 0, lt);
8436 break;
8437 case NEON_CMLE_zero_scalar:
8438 cmp(vf, rd, rn, 0, le);
8439 break;
8440 case NEON_ABS_scalar:
8441 abs(vf, rd, rn);
8442 break;
8443 case NEON_SQABS_scalar:
8444 abs(vf, rd, rn).SignedSaturate(vf);
8445 break;
8446 case NEON_NEG_scalar:
8447 neg(vf, rd, rn);
8448 break;
8449 case NEON_SQNEG_scalar:
8450 neg(vf, rd, rn).SignedSaturate(vf);
8451 break;
8452 case NEON_SUQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008453 suqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008454 break;
8455 case NEON_USQADD_scalar:
Martyn Capewell9b532192020-09-15 16:20:11 +01008456 usqadd(vf, rd, rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008457 break;
8458 default:
8459 VIXL_UNIMPLEMENTED();
8460 break;
8461 }
8462 } else {
8463 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8464 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8465
8466 // These instructions all use a one bit size field, except SQXTUN, SQXTN
8467 // and UQXTN, which use a two bit size field.
8468 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8469 case NEON_FRECPE_scalar:
8470 frecpe(fpf, rd, rn, fpcr_rounding);
8471 break;
8472 case NEON_FRECPX_scalar:
8473 frecpx(fpf, rd, rn);
8474 break;
8475 case NEON_FRSQRTE_scalar:
8476 frsqrte(fpf, rd, rn);
8477 break;
8478 case NEON_FCMGT_zero_scalar:
8479 fcmp_zero(fpf, rd, rn, gt);
8480 break;
8481 case NEON_FCMGE_zero_scalar:
8482 fcmp_zero(fpf, rd, rn, ge);
8483 break;
8484 case NEON_FCMEQ_zero_scalar:
8485 fcmp_zero(fpf, rd, rn, eq);
8486 break;
8487 case NEON_FCMLE_zero_scalar:
8488 fcmp_zero(fpf, rd, rn, le);
8489 break;
8490 case NEON_FCMLT_zero_scalar:
8491 fcmp_zero(fpf, rd, rn, lt);
8492 break;
8493 case NEON_SCVTF_scalar:
8494 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8495 break;
8496 case NEON_UCVTF_scalar:
8497 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8498 break;
8499 case NEON_FCVTNS_scalar:
8500 fcvts(fpf, rd, rn, FPTieEven);
8501 break;
8502 case NEON_FCVTNU_scalar:
8503 fcvtu(fpf, rd, rn, FPTieEven);
8504 break;
8505 case NEON_FCVTPS_scalar:
8506 fcvts(fpf, rd, rn, FPPositiveInfinity);
8507 break;
8508 case NEON_FCVTPU_scalar:
8509 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8510 break;
8511 case NEON_FCVTMS_scalar:
8512 fcvts(fpf, rd, rn, FPNegativeInfinity);
8513 break;
8514 case NEON_FCVTMU_scalar:
8515 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8516 break;
8517 case NEON_FCVTZS_scalar:
8518 fcvts(fpf, rd, rn, FPZero);
8519 break;
8520 case NEON_FCVTZU_scalar:
8521 fcvtu(fpf, rd, rn, FPZero);
8522 break;
8523 case NEON_FCVTAS_scalar:
8524 fcvts(fpf, rd, rn, FPTieAway);
8525 break;
8526 case NEON_FCVTAU_scalar:
8527 fcvtu(fpf, rd, rn, FPTieAway);
8528 break;
8529 case NEON_FCVTXN_scalar:
8530 // Unlike all of the other FP instructions above, fcvtxn encodes dest
8531 // size S as size<0>=1. There's only one case, so we ignore the form.
8532 VIXL_ASSERT(instr->ExtractBit(22) == 1);
8533 fcvtxn(kFormatS, rd, rn);
8534 break;
8535 default:
8536 switch (instr->Mask(NEONScalar2RegMiscMask)) {
8537 case NEON_SQXTN_scalar:
8538 sqxtn(vf, rd, rn);
8539 break;
8540 case NEON_UQXTN_scalar:
8541 uqxtn(vf, rd, rn);
8542 break;
8543 case NEON_SQXTUN_scalar:
8544 sqxtun(vf, rd, rn);
8545 break;
8546 default:
8547 VIXL_UNIMPLEMENTED();
8548 }
8549 }
8550 }
8551}
8552
8553
Jacob Bramleyca789742018-09-13 14:25:46 +01008554void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8555 VectorFormat fpf = kFormatH;
8556 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8557
8558 SimVRegister& rd = ReadVRegister(instr->GetRd());
8559 SimVRegister& rn = ReadVRegister(instr->GetRn());
8560
8561 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8562 case NEON_FRECPE_H_scalar:
8563 frecpe(fpf, rd, rn, fpcr_rounding);
8564 break;
8565 case NEON_FRECPX_H_scalar:
8566 frecpx(fpf, rd, rn);
8567 break;
8568 case NEON_FRSQRTE_H_scalar:
8569 frsqrte(fpf, rd, rn);
8570 break;
8571 case NEON_FCMGT_H_zero_scalar:
8572 fcmp_zero(fpf, rd, rn, gt);
8573 break;
8574 case NEON_FCMGE_H_zero_scalar:
8575 fcmp_zero(fpf, rd, rn, ge);
8576 break;
8577 case NEON_FCMEQ_H_zero_scalar:
8578 fcmp_zero(fpf, rd, rn, eq);
8579 break;
8580 case NEON_FCMLE_H_zero_scalar:
8581 fcmp_zero(fpf, rd, rn, le);
8582 break;
8583 case NEON_FCMLT_H_zero_scalar:
8584 fcmp_zero(fpf, rd, rn, lt);
8585 break;
8586 case NEON_SCVTF_H_scalar:
8587 scvtf(fpf, rd, rn, 0, fpcr_rounding);
8588 break;
8589 case NEON_UCVTF_H_scalar:
8590 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8591 break;
8592 case NEON_FCVTNS_H_scalar:
8593 fcvts(fpf, rd, rn, FPTieEven);
8594 break;
8595 case NEON_FCVTNU_H_scalar:
8596 fcvtu(fpf, rd, rn, FPTieEven);
8597 break;
8598 case NEON_FCVTPS_H_scalar:
8599 fcvts(fpf, rd, rn, FPPositiveInfinity);
8600 break;
8601 case NEON_FCVTPU_H_scalar:
8602 fcvtu(fpf, rd, rn, FPPositiveInfinity);
8603 break;
8604 case NEON_FCVTMS_H_scalar:
8605 fcvts(fpf, rd, rn, FPNegativeInfinity);
8606 break;
8607 case NEON_FCVTMU_H_scalar:
8608 fcvtu(fpf, rd, rn, FPNegativeInfinity);
8609 break;
8610 case NEON_FCVTZS_H_scalar:
8611 fcvts(fpf, rd, rn, FPZero);
8612 break;
8613 case NEON_FCVTZU_H_scalar:
8614 fcvtu(fpf, rd, rn, FPZero);
8615 break;
8616 case NEON_FCVTAS_H_scalar:
8617 fcvts(fpf, rd, rn, FPTieAway);
8618 break;
8619 case NEON_FCVTAU_H_scalar:
8620 fcvtu(fpf, rd, rn, FPTieAway);
8621 break;
8622 }
8623}
8624
8625
Alexandre Ramesd3832962016-07-04 15:03:43 +01008626void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8627 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8628 VectorFormat vf = nfd.GetVectorFormat();
8629
8630 SimVRegister& rd = ReadVRegister(instr->GetRd());
8631 SimVRegister& rn = ReadVRegister(instr->GetRn());
8632 SimVRegister& rm = ReadVRegister(instr->GetRm());
8633 switch (instr->Mask(NEONScalar3DiffMask)) {
8634 case NEON_SQDMLAL_scalar:
8635 sqdmlal(vf, rd, rn, rm);
8636 break;
8637 case NEON_SQDMLSL_scalar:
8638 sqdmlsl(vf, rd, rn, rm);
8639 break;
8640 case NEON_SQDMULL_scalar:
8641 sqdmull(vf, rd, rn, rm);
8642 break;
8643 default:
8644 VIXL_UNIMPLEMENTED();
8645 }
8646}
8647
8648
8649void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8650 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8651 VectorFormat vf = nfd.GetVectorFormat();
8652
8653 SimVRegister& rd = ReadVRegister(instr->GetRd());
8654 SimVRegister& rn = ReadVRegister(instr->GetRn());
8655 SimVRegister& rm = ReadVRegister(instr->GetRm());
8656
8657 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8658 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8659 switch (instr->Mask(NEONScalar3SameFPMask)) {
8660 case NEON_FMULX_scalar:
8661 fmulx(vf, rd, rn, rm);
8662 break;
8663 case NEON_FACGE_scalar:
8664 fabscmp(vf, rd, rn, rm, ge);
8665 break;
8666 case NEON_FACGT_scalar:
8667 fabscmp(vf, rd, rn, rm, gt);
8668 break;
8669 case NEON_FCMEQ_scalar:
8670 fcmp(vf, rd, rn, rm, eq);
8671 break;
8672 case NEON_FCMGE_scalar:
8673 fcmp(vf, rd, rn, rm, ge);
8674 break;
8675 case NEON_FCMGT_scalar:
8676 fcmp(vf, rd, rn, rm, gt);
8677 break;
8678 case NEON_FRECPS_scalar:
8679 frecps(vf, rd, rn, rm);
8680 break;
8681 case NEON_FRSQRTS_scalar:
8682 frsqrts(vf, rd, rn, rm);
8683 break;
8684 case NEON_FABD_scalar:
8685 fabd(vf, rd, rn, rm);
8686 break;
8687 default:
8688 VIXL_UNIMPLEMENTED();
8689 }
8690 } else {
8691 switch (instr->Mask(NEONScalar3SameMask)) {
8692 case NEON_ADD_scalar:
8693 add(vf, rd, rn, rm);
8694 break;
8695 case NEON_SUB_scalar:
8696 sub(vf, rd, rn, rm);
8697 break;
8698 case NEON_CMEQ_scalar:
8699 cmp(vf, rd, rn, rm, eq);
8700 break;
8701 case NEON_CMGE_scalar:
8702 cmp(vf, rd, rn, rm, ge);
8703 break;
8704 case NEON_CMGT_scalar:
8705 cmp(vf, rd, rn, rm, gt);
8706 break;
8707 case NEON_CMHI_scalar:
8708 cmp(vf, rd, rn, rm, hi);
8709 break;
8710 case NEON_CMHS_scalar:
8711 cmp(vf, rd, rn, rm, hs);
8712 break;
8713 case NEON_CMTST_scalar:
8714 cmptst(vf, rd, rn, rm);
8715 break;
8716 case NEON_USHL_scalar:
8717 ushl(vf, rd, rn, rm);
8718 break;
8719 case NEON_SSHL_scalar:
8720 sshl(vf, rd, rn, rm);
8721 break;
8722 case NEON_SQDMULH_scalar:
8723 sqdmulh(vf, rd, rn, rm);
8724 break;
8725 case NEON_SQRDMULH_scalar:
8726 sqrdmulh(vf, rd, rn, rm);
8727 break;
8728 case NEON_UQADD_scalar:
8729 add(vf, rd, rn, rm).UnsignedSaturate(vf);
8730 break;
8731 case NEON_SQADD_scalar:
8732 add(vf, rd, rn, rm).SignedSaturate(vf);
8733 break;
8734 case NEON_UQSUB_scalar:
8735 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8736 break;
8737 case NEON_SQSUB_scalar:
8738 sub(vf, rd, rn, rm).SignedSaturate(vf);
8739 break;
8740 case NEON_UQSHL_scalar:
8741 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8742 break;
8743 case NEON_SQSHL_scalar:
8744 sshl(vf, rd, rn, rm).SignedSaturate(vf);
8745 break;
8746 case NEON_URSHL_scalar:
8747 ushl(vf, rd, rn, rm).Round(vf);
8748 break;
8749 case NEON_SRSHL_scalar:
8750 sshl(vf, rd, rn, rm).Round(vf);
8751 break;
8752 case NEON_UQRSHL_scalar:
8753 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8754 break;
8755 case NEON_SQRSHL_scalar:
8756 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8757 break;
8758 default:
8759 VIXL_UNIMPLEMENTED();
8760 }
8761 }
8762}
8763
Jacob Bramleyca789742018-09-13 14:25:46 +01008764void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8765 SimVRegister& rd = ReadVRegister(instr->GetRd());
8766 SimVRegister& rn = ReadVRegister(instr->GetRn());
8767 SimVRegister& rm = ReadVRegister(instr->GetRm());
8768
8769 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8770 case NEON_FABD_H_scalar:
8771 fabd(kFormatH, rd, rn, rm);
8772 break;
8773 case NEON_FMULX_H_scalar:
8774 fmulx(kFormatH, rd, rn, rm);
8775 break;
8776 case NEON_FCMEQ_H_scalar:
8777 fcmp(kFormatH, rd, rn, rm, eq);
8778 break;
8779 case NEON_FCMGE_H_scalar:
8780 fcmp(kFormatH, rd, rn, rm, ge);
8781 break;
8782 case NEON_FCMGT_H_scalar:
8783 fcmp(kFormatH, rd, rn, rm, gt);
8784 break;
8785 case NEON_FACGE_H_scalar:
8786 fabscmp(kFormatH, rd, rn, rm, ge);
8787 break;
8788 case NEON_FACGT_H_scalar:
8789 fabscmp(kFormatH, rd, rn, rm, gt);
8790 break;
8791 case NEON_FRECPS_H_scalar:
8792 frecps(kFormatH, rd, rn, rm);
8793 break;
8794 case NEON_FRSQRTS_H_scalar:
8795 frsqrts(kFormatH, rd, rn, rm);
8796 break;
8797 default:
8798 VIXL_UNREACHABLE();
8799 }
8800}
8801
Alexandre Ramesd3832962016-07-04 15:03:43 +01008802
Alexander Gilday43785642018-04-04 13:42:33 +01008803void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8804 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8805 VectorFormat vf = nfd.GetVectorFormat();
8806
8807 SimVRegister& rd = ReadVRegister(instr->GetRd());
8808 SimVRegister& rn = ReadVRegister(instr->GetRn());
8809 SimVRegister& rm = ReadVRegister(instr->GetRm());
8810
8811 switch (instr->Mask(NEONScalar3SameExtraMask)) {
8812 case NEON_SQRDMLAH_scalar:
8813 sqrdmlah(vf, rd, rn, rm);
8814 break;
8815 case NEON_SQRDMLSH_scalar:
8816 sqrdmlsh(vf, rd, rn, rm);
8817 break;
8818 default:
8819 VIXL_UNIMPLEMENTED();
8820 }
8821}
8822
Alexandre Ramesd3832962016-07-04 15:03:43 +01008823void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8824 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8825 VectorFormat vf = nfd.GetVectorFormat();
8826 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8827
8828 SimVRegister& rd = ReadVRegister(instr->GetRd());
8829 SimVRegister& rn = ReadVRegister(instr->GetRn());
8830 ByElementOp Op = NULL;
8831
8832 int rm_reg = instr->GetRm();
8833 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8834 if (instr->GetNEONSize() == 1) {
8835 rm_reg &= 0xf;
8836 index = (index << 1) | instr->GetNEONM();
8837 }
8838
8839 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8840 case NEON_SQDMULL_byelement_scalar:
8841 Op = &Simulator::sqdmull;
8842 break;
8843 case NEON_SQDMLAL_byelement_scalar:
8844 Op = &Simulator::sqdmlal;
8845 break;
8846 case NEON_SQDMLSL_byelement_scalar:
8847 Op = &Simulator::sqdmlsl;
8848 break;
8849 case NEON_SQDMULH_byelement_scalar:
8850 Op = &Simulator::sqdmulh;
8851 vf = vf_r;
8852 break;
8853 case NEON_SQRDMULH_byelement_scalar:
8854 Op = &Simulator::sqrdmulh;
8855 vf = vf_r;
8856 break;
Alexander Gilday43785642018-04-04 13:42:33 +01008857 case NEON_SQRDMLAH_byelement_scalar:
8858 Op = &Simulator::sqrdmlah;
8859 vf = vf_r;
8860 break;
8861 case NEON_SQRDMLSH_byelement_scalar:
8862 Op = &Simulator::sqrdmlsh;
8863 vf = vf_r;
8864 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01008865 default:
8866 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8867 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01008868 if (instr->GetFPType() == 0) {
8869 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8870 rm_reg &= 0xf;
8871 vf = kFormatH;
8872 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008873 index = (index << 1) | instr->GetNEONL();
8874 }
8875 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008876 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008877 case NEON_FMUL_byelement_scalar:
8878 Op = &Simulator::fmul;
8879 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008880 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008881 case NEON_FMLA_byelement_scalar:
8882 Op = &Simulator::fmla;
8883 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008884 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008885 case NEON_FMLS_byelement_scalar:
8886 Op = &Simulator::fmls;
8887 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008888 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008889 case NEON_FMULX_byelement_scalar:
8890 Op = &Simulator::fmulx;
8891 break;
8892 default:
8893 VIXL_UNIMPLEMENTED();
8894 }
8895 }
8896
8897 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8898}
8899
8900
8901void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8902 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8903 VectorFormat vf = nfd.GetVectorFormat();
8904
8905 SimVRegister& rd = ReadVRegister(instr->GetRd());
8906 SimVRegister& rn = ReadVRegister(instr->GetRn());
8907
8908 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8909 int imm5 = instr->GetImmNEON5();
8910 int tz = CountTrailingZeros(imm5, 32);
8911 int rn_index = imm5 >> (tz + 1);
8912 dup_element(vf, rd, rn, rn_index);
8913 } else {
8914 VIXL_UNIMPLEMENTED();
8915 }
8916}
8917
8918
8919void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008920 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008921 VectorFormat vf = nfd.GetVectorFormat();
8922
8923 SimVRegister& rd = ReadVRegister(instr->GetRd());
8924 SimVRegister& rn = ReadVRegister(instr->GetRn());
8925 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01008926 case NEON_ADDP_scalar: {
8927 // All pairwise operations except ADDP use bit U to differentiate FP16
8928 // from FP32/FP64 variations.
8929 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8930 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008931 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008932 }
8933 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008934 case NEON_FADDP_scalar:
8935 faddp(vf, rd, rn);
8936 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008937 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008938 case NEON_FMAXP_scalar:
8939 fmaxp(vf, rd, rn);
8940 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008941 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008942 case NEON_FMAXNMP_scalar:
8943 fmaxnmp(vf, rd, rn);
8944 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008945 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008946 case NEON_FMINP_scalar:
8947 fminp(vf, rd, rn);
8948 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01008949 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01008950 case NEON_FMINNMP_scalar:
8951 fminnmp(vf, rd, rn);
8952 break;
8953 default:
8954 VIXL_UNIMPLEMENTED();
8955 }
8956}
8957
8958
8959void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
8960 SimVRegister& rd = ReadVRegister(instr->GetRd());
8961 SimVRegister& rn = ReadVRegister(instr->GetRn());
8962 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8963
8964 static const NEONFormatMap map = {{22, 21, 20, 19},
8965 {NF_UNDEF,
8966 NF_B,
8967 NF_H,
8968 NF_H,
8969 NF_S,
8970 NF_S,
8971 NF_S,
8972 NF_S,
8973 NF_D,
8974 NF_D,
8975 NF_D,
8976 NF_D,
8977 NF_D,
8978 NF_D,
8979 NF_D,
8980 NF_D}};
8981 NEONFormatDecoder nfd(instr, &map);
8982 VectorFormat vf = nfd.GetVectorFormat();
8983
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00008984 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
8985 int immh_immb = instr->GetImmNEONImmhImmb();
8986 int right_shift = (16 << highest_set_bit) - immh_immb;
8987 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008988 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
8989 case NEON_SHL_scalar:
8990 shl(vf, rd, rn, left_shift);
8991 break;
8992 case NEON_SLI_scalar:
8993 sli(vf, rd, rn, left_shift);
8994 break;
8995 case NEON_SQSHL_imm_scalar:
8996 sqshl(vf, rd, rn, left_shift);
8997 break;
8998 case NEON_UQSHL_imm_scalar:
8999 uqshl(vf, rd, rn, left_shift);
9000 break;
9001 case NEON_SQSHLU_scalar:
9002 sqshlu(vf, rd, rn, left_shift);
9003 break;
9004 case NEON_SRI_scalar:
9005 sri(vf, rd, rn, right_shift);
9006 break;
9007 case NEON_SSHR_scalar:
9008 sshr(vf, rd, rn, right_shift);
9009 break;
9010 case NEON_USHR_scalar:
9011 ushr(vf, rd, rn, right_shift);
9012 break;
9013 case NEON_SRSHR_scalar:
9014 sshr(vf, rd, rn, right_shift).Round(vf);
9015 break;
9016 case NEON_URSHR_scalar:
9017 ushr(vf, rd, rn, right_shift).Round(vf);
9018 break;
9019 case NEON_SSRA_scalar:
9020 ssra(vf, rd, rn, right_shift);
9021 break;
9022 case NEON_USRA_scalar:
9023 usra(vf, rd, rn, right_shift);
9024 break;
9025 case NEON_SRSRA_scalar:
9026 srsra(vf, rd, rn, right_shift);
9027 break;
9028 case NEON_URSRA_scalar:
9029 ursra(vf, rd, rn, right_shift);
9030 break;
9031 case NEON_UQSHRN_scalar:
9032 uqshrn(vf, rd, rn, right_shift);
9033 break;
9034 case NEON_UQRSHRN_scalar:
9035 uqrshrn(vf, rd, rn, right_shift);
9036 break;
9037 case NEON_SQSHRN_scalar:
9038 sqshrn(vf, rd, rn, right_shift);
9039 break;
9040 case NEON_SQRSHRN_scalar:
9041 sqrshrn(vf, rd, rn, right_shift);
9042 break;
9043 case NEON_SQSHRUN_scalar:
9044 sqshrun(vf, rd, rn, right_shift);
9045 break;
9046 case NEON_SQRSHRUN_scalar:
9047 sqrshrun(vf, rd, rn, right_shift);
9048 break;
9049 case NEON_FCVTZS_imm_scalar:
9050 fcvts(vf, rd, rn, FPZero, right_shift);
9051 break;
9052 case NEON_FCVTZU_imm_scalar:
9053 fcvtu(vf, rd, rn, FPZero, right_shift);
9054 break;
9055 case NEON_SCVTF_imm_scalar:
9056 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9057 break;
9058 case NEON_UCVTF_imm_scalar:
9059 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9060 break;
9061 default:
9062 VIXL_UNIMPLEMENTED();
9063 }
9064}
9065
9066
9067void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9068 SimVRegister& rd = ReadVRegister(instr->GetRd());
9069 SimVRegister& rn = ReadVRegister(instr->GetRn());
9070 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9071
9072 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9073 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9074 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01009075 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
9076 NF_4H, NF_8H, NF_4H, NF_8H,
9077 NF_2S, NF_4S, NF_2S, NF_4S,
9078 NF_2S, NF_4S, NF_2S, NF_4S,
9079 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9080 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9081 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9082 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01009083 NEONFormatDecoder nfd(instr, &map);
9084 VectorFormat vf = nfd.GetVectorFormat();
9085
9086 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9087 static const NEONFormatMap map_l =
9088 {{22, 21, 20, 19},
9089 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9090 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9091
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00009092 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9093 int immh_immb = instr->GetImmNEONImmhImmb();
9094 int right_shift = (16 << highest_set_bit) - immh_immb;
9095 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009096
9097 switch (instr->Mask(NEONShiftImmediateMask)) {
9098 case NEON_SHL:
9099 shl(vf, rd, rn, left_shift);
9100 break;
9101 case NEON_SLI:
9102 sli(vf, rd, rn, left_shift);
9103 break;
9104 case NEON_SQSHLU:
9105 sqshlu(vf, rd, rn, left_shift);
9106 break;
9107 case NEON_SRI:
9108 sri(vf, rd, rn, right_shift);
9109 break;
9110 case NEON_SSHR:
9111 sshr(vf, rd, rn, right_shift);
9112 break;
9113 case NEON_USHR:
9114 ushr(vf, rd, rn, right_shift);
9115 break;
9116 case NEON_SRSHR:
9117 sshr(vf, rd, rn, right_shift).Round(vf);
9118 break;
9119 case NEON_URSHR:
9120 ushr(vf, rd, rn, right_shift).Round(vf);
9121 break;
9122 case NEON_SSRA:
9123 ssra(vf, rd, rn, right_shift);
9124 break;
9125 case NEON_USRA:
9126 usra(vf, rd, rn, right_shift);
9127 break;
9128 case NEON_SRSRA:
9129 srsra(vf, rd, rn, right_shift);
9130 break;
9131 case NEON_URSRA:
9132 ursra(vf, rd, rn, right_shift);
9133 break;
9134 case NEON_SQSHL_imm:
9135 sqshl(vf, rd, rn, left_shift);
9136 break;
9137 case NEON_UQSHL_imm:
9138 uqshl(vf, rd, rn, left_shift);
9139 break;
9140 case NEON_SCVTF_imm:
9141 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9142 break;
9143 case NEON_UCVTF_imm:
9144 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9145 break;
9146 case NEON_FCVTZS_imm:
9147 fcvts(vf, rd, rn, FPZero, right_shift);
9148 break;
9149 case NEON_FCVTZU_imm:
9150 fcvtu(vf, rd, rn, FPZero, right_shift);
9151 break;
9152 case NEON_SSHLL:
9153 vf = vf_l;
9154 if (instr->Mask(NEON_Q)) {
9155 sshll2(vf, rd, rn, left_shift);
9156 } else {
9157 sshll(vf, rd, rn, left_shift);
9158 }
9159 break;
9160 case NEON_USHLL:
9161 vf = vf_l;
9162 if (instr->Mask(NEON_Q)) {
9163 ushll2(vf, rd, rn, left_shift);
9164 } else {
9165 ushll(vf, rd, rn, left_shift);
9166 }
9167 break;
9168 case NEON_SHRN:
9169 if (instr->Mask(NEON_Q)) {
9170 shrn2(vf, rd, rn, right_shift);
9171 } else {
9172 shrn(vf, rd, rn, right_shift);
9173 }
9174 break;
9175 case NEON_RSHRN:
9176 if (instr->Mask(NEON_Q)) {
9177 rshrn2(vf, rd, rn, right_shift);
9178 } else {
9179 rshrn(vf, rd, rn, right_shift);
9180 }
9181 break;
9182 case NEON_UQSHRN:
9183 if (instr->Mask(NEON_Q)) {
9184 uqshrn2(vf, rd, rn, right_shift);
9185 } else {
9186 uqshrn(vf, rd, rn, right_shift);
9187 }
9188 break;
9189 case NEON_UQRSHRN:
9190 if (instr->Mask(NEON_Q)) {
9191 uqrshrn2(vf, rd, rn, right_shift);
9192 } else {
9193 uqrshrn(vf, rd, rn, right_shift);
9194 }
9195 break;
9196 case NEON_SQSHRN:
9197 if (instr->Mask(NEON_Q)) {
9198 sqshrn2(vf, rd, rn, right_shift);
9199 } else {
9200 sqshrn(vf, rd, rn, right_shift);
9201 }
9202 break;
9203 case NEON_SQRSHRN:
9204 if (instr->Mask(NEON_Q)) {
9205 sqrshrn2(vf, rd, rn, right_shift);
9206 } else {
9207 sqrshrn(vf, rd, rn, right_shift);
9208 }
9209 break;
9210 case NEON_SQSHRUN:
9211 if (instr->Mask(NEON_Q)) {
9212 sqshrun2(vf, rd, rn, right_shift);
9213 } else {
9214 sqshrun(vf, rd, rn, right_shift);
9215 }
9216 break;
9217 case NEON_SQRSHRUN:
9218 if (instr->Mask(NEON_Q)) {
9219 sqrshrun2(vf, rd, rn, right_shift);
9220 } else {
9221 sqrshrun(vf, rd, rn, right_shift);
9222 }
9223 break;
9224 default:
9225 VIXL_UNIMPLEMENTED();
9226 }
9227}
9228
9229
9230void Simulator::VisitNEONTable(const Instruction* instr) {
9231 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9232 VectorFormat vf = nfd.GetVectorFormat();
9233
9234 SimVRegister& rd = ReadVRegister(instr->GetRd());
9235 SimVRegister& rn = ReadVRegister(instr->GetRn());
9236 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9237 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9238 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9239 SimVRegister& rm = ReadVRegister(instr->GetRm());
9240
9241 switch (instr->Mask(NEONTableMask)) {
9242 case NEON_TBL_1v:
9243 tbl(vf, rd, rn, rm);
9244 break;
9245 case NEON_TBL_2v:
9246 tbl(vf, rd, rn, rn2, rm);
9247 break;
9248 case NEON_TBL_3v:
9249 tbl(vf, rd, rn, rn2, rn3, rm);
9250 break;
9251 case NEON_TBL_4v:
9252 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9253 break;
9254 case NEON_TBX_1v:
9255 tbx(vf, rd, rn, rm);
9256 break;
9257 case NEON_TBX_2v:
9258 tbx(vf, rd, rn, rn2, rm);
9259 break;
9260 case NEON_TBX_3v:
9261 tbx(vf, rd, rn, rn2, rn3, rm);
9262 break;
9263 case NEON_TBX_4v:
9264 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9265 break;
9266 default:
9267 VIXL_UNIMPLEMENTED();
9268 }
9269}
9270
9271
9272void Simulator::VisitNEONPerm(const Instruction* instr) {
9273 NEONFormatDecoder nfd(instr);
9274 VectorFormat vf = nfd.GetVectorFormat();
9275
9276 SimVRegister& rd = ReadVRegister(instr->GetRd());
9277 SimVRegister& rn = ReadVRegister(instr->GetRn());
9278 SimVRegister& rm = ReadVRegister(instr->GetRm());
9279
9280 switch (instr->Mask(NEONPermMask)) {
9281 case NEON_TRN1:
9282 trn1(vf, rd, rn, rm);
9283 break;
9284 case NEON_TRN2:
9285 trn2(vf, rd, rn, rm);
9286 break;
9287 case NEON_UZP1:
9288 uzp1(vf, rd, rn, rm);
9289 break;
9290 case NEON_UZP2:
9291 uzp2(vf, rd, rn, rm);
9292 break;
9293 case NEON_ZIP1:
9294 zip1(vf, rd, rn, rm);
9295 break;
9296 case NEON_ZIP2:
9297 zip2(vf, rd, rn, rm);
9298 break;
9299 default:
9300 VIXL_UNIMPLEMENTED();
9301 }
9302}
9303
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009304void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00009305 SimVRegister& zd = ReadVRegister(instr->GetRd());
9306 SimVRegister& zn = ReadVRegister(instr->GetRn());
9307 SimVRegister& zm = ReadVRegister(instr->GetRm());
9308 SimVRegister temp;
9309
9310 VectorFormat vform = kFormatVnD;
9311 mov(vform, temp, zm);
9312
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009313 switch (instr->Mask(SVEAddressGenerationMask)) {
9314 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009315 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009316 break;
9317 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00009318 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009319 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00009320 case ADR_z_az_s_same_scaled:
9321 vform = kFormatVnS;
9322 break;
9323 case ADR_z_az_d_same_scaled:
9324 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009325 break;
9326 default:
9327 VIXL_UNIMPLEMENTED();
9328 break;
9329 }
Martyn Capewell48522f52020-03-16 15:31:19 +00009330
9331 int shift_amount = instr->ExtractBits(11, 10);
9332 shl(vform, temp, temp, shift_amount);
9333 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009334}
9335
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009336void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9337 const Instruction* instr) {
9338 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07009339 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009340 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009341 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07009342 case ORR_z_zi: {
9343 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9344 uint64_t imm = instr->GetSVEImmLogical();
9345 // Valid immediate is a non-zero bits
9346 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009347 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9348 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07009349 SVEFormatFromLaneSizeInBytesLog2(lane_size),
9350 ReadVRegister(instr->GetRd()),
9351 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009352 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07009353 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009354 default:
9355 VIXL_UNIMPLEMENTED();
9356 break;
9357 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009358}
9359
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009360void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9361 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9362 case DUPM_z_i: {
9363 /* DUPM uses the same lane size and immediate encoding as bitwise logical
9364 * immediate instructions. */
9365 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9366 uint64_t imm = instr->GetSVEImmLogical();
9367 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9368 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9369 break;
9370 }
9371 default:
9372 VIXL_UNIMPLEMENTED();
9373 break;
9374 }
9375}
9376
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009377void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07009378 SimVRegister& zd = ReadVRegister(instr->GetRd());
9379 SimVRegister& zn = ReadVRegister(instr->GetRn());
9380 SimVRegister& zm = ReadVRegister(instr->GetRm());
9381 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9382
TatWai Chong13634762019-07-16 16:20:45 -07009383 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07009384 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009385 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009386 logical_op = AND;
9387 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009388 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009389 logical_op = BIC;
9390 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009391 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009392 logical_op = EOR;
9393 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07009394 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07009395 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009396 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009397 default:
TatWai Chong13634762019-07-16 16:20:45 -07009398 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009399 VIXL_UNIMPLEMENTED();
9400 break;
9401 }
TatWai Chong13634762019-07-16 16:20:45 -07009402 // Lane size of registers is irrelevant to the bitwise operations, so perform
9403 // the operation on D-sized lanes.
9404 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009405}
9406
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009407void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00009408 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9409 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9410
9411 SimVRegister scratch;
9412 SimVRegister result;
9413
9414 bool for_division = false;
9415 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009416 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009417 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009418 shift_op = ASR;
9419 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009420 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009421 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009422 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009423 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009424 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009425 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009426 break;
9427 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00009428 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009429 break;
9430 default:
9431 VIXL_UNIMPLEMENTED();
9432 break;
9433 }
Martyn Capewell83e86612020-02-19 15:46:15 +00009434
9435 std::pair<int, int> shift_and_lane_size =
9436 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9437 unsigned lane_size = shift_and_lane_size.second;
9438 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9439 int shift_dist = shift_and_lane_size.first;
9440
9441 if ((shift_op == ASR) && for_division) {
9442 asrd(vform, result, zdn, shift_dist);
9443 } else {
9444 if (shift_op == LSL) {
9445 // Shift distance is computed differently for LSL. Convert the result.
9446 shift_dist = (8 << lane_size) - shift_dist;
9447 }
9448 dup_immediate(vform, scratch, shift_dist);
9449 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9450 }
9451 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009452}
9453
9454void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9455 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009456 VectorFormat vform = instr->GetSVEVectorFormat();
9457 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9458 SimVRegister& zm = ReadVRegister(instr->GetRn());
9459 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
Martyn Capewell76c094a2020-02-13 17:26:49 +00009460 SimVRegister result;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009461
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009462 // SVE uses the whole (saturated) lane for the shift amount.
9463 bool shift_in_ls_byte = false;
Martyn Capewell76c094a2020-02-13 17:26:49 +00009464
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009465 switch (form_hash_) {
9466 case Hash("asrr_z_p_zz"):
9467 sshr(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009468 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009469 case Hash("asr_z_p_zz"):
9470 sshr(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009471 break;
Martyn Capewell42bd8e92020-09-09 18:34:44 +01009472 case Hash("lslr_z_p_zz"):
9473 sshl(vform, result, zm, zdn, shift_in_ls_byte);
9474 break;
9475 case Hash("lsl_z_p_zz"):
9476 sshl(vform, result, zdn, zm, shift_in_ls_byte);
9477 break;
9478 case Hash("lsrr_z_p_zz"):
9479 ushr(vform, result, zm, zdn);
9480 break;
9481 case Hash("lsr_z_p_zz"):
9482 ushr(vform, result, zdn, zm);
9483 break;
9484 case Hash("sqrshl_z_p_zz"):
9485 sshl(vform, result, zdn, zm, shift_in_ls_byte)
9486 .Round(vform)
9487 .SignedSaturate(vform);
9488 break;
9489 case Hash("sqrshlr_z_p_zz"):
9490 sshl(vform, result, zm, zdn, shift_in_ls_byte)
9491 .Round(vform)
9492 .SignedSaturate(vform);
9493 break;
9494 case Hash("sqshl_z_p_zz"):
9495 sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
9496 break;
9497 case Hash("sqshlr_z_p_zz"):
9498 sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
9499 break;
9500 case Hash("srshl_z_p_zz"):
9501 sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9502 break;
9503 case Hash("srshlr_z_p_zz"):
9504 sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9505 break;
9506 case Hash("uqrshl_z_p_zz"):
9507 ushl(vform, result, zdn, zm, shift_in_ls_byte)
9508 .Round(vform)
9509 .UnsignedSaturate(vform);
9510 break;
9511 case Hash("uqrshlr_z_p_zz"):
9512 ushl(vform, result, zm, zdn, shift_in_ls_byte)
9513 .Round(vform)
9514 .UnsignedSaturate(vform);
9515 break;
9516 case Hash("uqshl_z_p_zz"):
9517 ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
9518 break;
9519 case Hash("uqshlr_z_p_zz"):
9520 ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
9521 break;
9522 case Hash("urshl_z_p_zz"):
9523 ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9524 break;
9525 case Hash("urshlr_z_p_zz"):
9526 ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009527 break;
9528 default:
9529 VIXL_UNIMPLEMENTED();
9530 break;
9531 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009532 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009533}
9534
9535void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9536 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00009537 VectorFormat vform = instr->GetSVEVectorFormat();
9538 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9539 SimVRegister& zm = ReadVRegister(instr->GetRn());
9540 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9541
9542 SimVRegister result;
9543 Shift shift_op = ASR;
9544
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009545 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9546 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009547 break;
9548 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009549 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009550 break;
9551 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00009552 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009553 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009554 default:
9555 VIXL_UNIMPLEMENTED();
9556 break;
9557 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00009558 SVEBitwiseShiftHelper(shift_op,
9559 vform,
9560 result,
9561 zdn,
9562 zm,
9563 /* is_wide_elements = */ true);
9564 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009565}
9566
9567void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08009568 SimVRegister& zd = ReadVRegister(instr->GetRd());
9569 SimVRegister& zn = ReadVRegister(instr->GetRn());
9570
9571 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009572 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9573 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009574 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009575 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009576 break;
9577 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009578 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009579 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009580 break;
9581 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08009582 case LSR_z_zw:
9583 shift_op = LSR;
9584 break;
9585 default:
9586 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009587 VIXL_UNIMPLEMENTED();
9588 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08009589 }
9590
9591 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9592 case ASR_z_zi:
9593 case LSL_z_zi:
9594 case LSR_z_zi: {
9595 SimVRegister scratch;
9596 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00009597 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08009598 unsigned lane_size = shift_and_lane_size.second;
9599 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9600 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00009601 int shift_dist = shift_and_lane_size.first;
9602 if (shift_op == LSL) {
9603 // Shift distance is computed differently for LSL. Convert the result.
9604 shift_dist = (8 << lane_size) - shift_dist;
9605 }
9606 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08009607 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9608 break;
9609 }
9610 case ASR_z_zw:
9611 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009612 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08009613 SVEBitwiseShiftHelper(shift_op,
9614 instr->GetSVEVectorFormat(),
9615 zd,
9616 zn,
9617 ReadVRegister(instr->GetRm()),
9618 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009619 break;
9620 default:
9621 VIXL_UNIMPLEMENTED();
9622 break;
9623 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009624}
9625
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009626void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00009627 // Although the instructions have a separate encoding class, the lane size is
9628 // encoded in the same way as most other SVE instructions.
9629 VectorFormat vform = instr->GetSVEVectorFormat();
9630
9631 int pattern = instr->GetImmSVEPredicateConstraint();
9632 int count = GetPredicateConstraintLaneCount(vform, pattern);
9633 int multiplier = instr->ExtractBits(19, 16) + 1;
9634
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009635 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009636 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009637 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009638 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009639 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009640 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009641 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009642 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009643 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009644 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009645 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00009646 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009647 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009648 default:
9649 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00009650 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009651 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00009652
9653 WriteXRegister(instr->GetRd(),
9654 IncDecN(ReadXRegister(instr->GetRd()),
9655 count * multiplier,
9656 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009657}
9658
9659void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009660 VectorFormat vform = instr->GetSVEVectorFormat();
9661 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9662 VIXL_UNIMPLEMENTED();
9663 }
9664
9665 int pattern = instr->GetImmSVEPredicateConstraint();
9666 int count = GetPredicateConstraintLaneCount(vform, pattern);
9667 int multiplier = instr->ExtractBits(19, 16) + 1;
9668
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009669 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9670 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009671 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009672 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009673 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009674 break;
9675 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009676 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009677 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009678 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009679 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009680 default:
9681 VIXL_UNIMPLEMENTED();
9682 break;
9683 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009684
9685 SimVRegister& zd = ReadVRegister(instr->GetRd());
9686 SimVRegister scratch;
9687 dup_immediate(vform,
9688 scratch,
9689 IncDecN(0,
9690 count * multiplier,
9691 LaneSizeInBitsFromFormat(vform)));
9692 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009693}
9694
9695void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9696 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009697 // Although the instructions have a separate encoding class, the lane size is
9698 // encoded in the same way as most other SVE instructions.
9699 VectorFormat vform = instr->GetSVEVectorFormat();
9700
9701 int pattern = instr->GetImmSVEPredicateConstraint();
9702 int count = GetPredicateConstraintLaneCount(vform, pattern);
9703 int multiplier = instr->ExtractBits(19, 16) + 1;
9704
9705 unsigned width = kXRegSize;
9706 bool is_signed = false;
9707
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009708 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009709 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009710 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009711 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009712 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009713 width = kWRegSize;
9714 VIXL_FALLTHROUGH();
9715 case SQDECB_r_rs_x:
9716 case SQDECD_r_rs_x:
9717 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009718 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009719 is_signed = true;
9720 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009721 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009722 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009723 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009724 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009725 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009726 width = kWRegSize;
9727 VIXL_FALLTHROUGH();
9728 case SQINCB_r_rs_x:
9729 case SQINCD_r_rs_x:
9730 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009731 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009732 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009733 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009734 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009735 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009736 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009737 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009738 width = kWRegSize;
9739 VIXL_FALLTHROUGH();
9740 case UQDECB_r_rs_x:
9741 case UQDECD_r_rs_x:
9742 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009743 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009744 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009745 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009746 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009747 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009748 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009749 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009750 width = kWRegSize;
9751 VIXL_FALLTHROUGH();
9752 case UQINCB_r_rs_x:
9753 case UQINCD_r_rs_x:
9754 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009755 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009756 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009757 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009758 default:
9759 VIXL_UNIMPLEMENTED();
9760 break;
9761 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00009762
9763 WriteXRegister(instr->GetRd(),
9764 IncDecN(ReadXRegister(instr->GetRd()),
9765 count * multiplier,
9766 width,
9767 true,
9768 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009769}
9770
9771void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9772 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009773 VectorFormat vform = instr->GetSVEVectorFormat();
9774 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9775 VIXL_UNIMPLEMENTED();
9776 }
9777
9778 int pattern = instr->GetImmSVEPredicateConstraint();
9779 int count = GetPredicateConstraintLaneCount(vform, pattern);
9780 int multiplier = instr->ExtractBits(19, 16) + 1;
9781
9782 SimVRegister& zd = ReadVRegister(instr->GetRd());
9783 SimVRegister scratch;
9784 dup_immediate(vform,
9785 scratch,
9786 IncDecN(0,
9787 count * multiplier,
9788 LaneSizeInBitsFromFormat(vform)));
9789
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009790 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9791 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009792 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009793 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009794 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009795 break;
9796 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009797 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009798 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009799 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009800 break;
9801 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009802 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009803 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009804 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009805 break;
9806 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009807 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009808 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00009809 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
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::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009818 switch (instr->Mask(SVEElementCountMask)) {
9819 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009820 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009821 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009822 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00009823 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009824 break;
9825 default:
9826 VIXL_UNIMPLEMENTED();
9827 break;
9828 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00009829
9830 // Although the instructions are separated, the lane size is encoded in the
9831 // same way as most other SVE instructions.
9832 VectorFormat vform = instr->GetSVEVectorFormat();
9833
9834 int pattern = instr->GetImmSVEPredicateConstraint();
9835 int count = GetPredicateConstraintLaneCount(vform, pattern);
9836 int multiplier = instr->ExtractBits(19, 16) + 1;
9837 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009838}
9839
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009840void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009841 VectorFormat vform = instr->GetSVEVectorFormat();
9842 SimVRegister& vdn = ReadVRegister(instr->GetRd());
9843 SimVRegister& zm = ReadVRegister(instr->GetRn());
9844 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9845
Martyn Capewell310a0822020-09-08 20:09:17 +01009846 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9847
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009848 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9849 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00009850 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009851 break;
9852 default:
9853 VIXL_UNIMPLEMENTED();
9854 break;
9855 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009856}
9857
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009858void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07009859 VectorFormat vform = instr->GetSVEVectorFormat();
9860 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9861 SimVRegister& zm = ReadVRegister(instr->GetRn());
9862 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9863
Martyn Capewell310a0822020-09-08 20:09:17 +01009864 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
TatWai Chongd316c5e2019-10-16 12:22:10 -07009865
Martyn Capewell310a0822020-09-08 20:09:17 +01009866 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009867 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009868 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009869 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009870 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009871 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009872 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009873 break;
9874 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009875 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009876 break;
9877 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07009878 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009879 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009880 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009881 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009882 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009883 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009884 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009885 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009886 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009887 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009888 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009889 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07009890 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009891 break;
9892 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009893 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009894 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009895 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009896 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009897 break;
9898 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009899 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009900 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009901 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009902 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009903 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009904 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00009905 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009906 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009907 default:
9908 VIXL_UNIMPLEMENTED();
9909 break;
9910 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07009911 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009912}
9913
9914void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9915 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00009916 VectorFormat vform = instr->GetSVEVectorFormat();
9917 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9918 VIXL_UNIMPLEMENTED();
9919 }
9920
9921 SimVRegister& zdn = ReadVRegister(instr->GetRd());
9922 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9923 SimVRegister result;
9924
9925 int i1 = instr->ExtractBit(5);
9926 SimVRegister add_sub_imm, min_max_imm, mul_imm;
9927 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9928 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9929 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9930 dup_immediate(vform, add_sub_imm, i1 ? one : half);
9931 dup_immediate(vform, min_max_imm, i1 ? one : 0);
9932 dup_immediate(vform, mul_imm, i1 ? two : half);
9933
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009934 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9935 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009936 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009937 break;
9938 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009939 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009940 break;
9941 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009942 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009943 break;
9944 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009945 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009946 break;
9947 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009948 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009949 break;
9950 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009951 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009952 break;
9953 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009954 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009955 break;
9956 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00009957 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009958 break;
9959 default:
9960 VIXL_UNIMPLEMENTED();
9961 break;
9962 }
Martyn Capewella2fadc22020-01-16 16:09:55 +00009963 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009964}
9965
9966void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009967 VectorFormat vform = instr->GetSVEVectorFormat();
9968 SimVRegister& zd = ReadVRegister(instr->GetRd());
9969 SimVRegister& zm = ReadVRegister(instr->GetRn());
9970
Martyn Capewell310a0822020-09-08 20:09:17 +01009971 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9972
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009973 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009974 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00009975 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009976 break;
9977 default:
9978 VIXL_UNIMPLEMENTED();
9979 break;
9980 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009981}
9982
9983void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -07009984 VectorFormat vform = instr->GetSVEVectorFormat();
9985 SimVRegister& zd = ReadVRegister(instr->GetRd());
9986 SimVRegister& zn = ReadVRegister(instr->GetRn());
9987 SimVRegister& zm = ReadVRegister(instr->GetRm());
9988
Martyn Capewell310a0822020-09-08 20:09:17 +01009989 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9990
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009991 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
9992 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009993 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009994 break;
9995 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07009996 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009997 break;
9998 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00009999 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010000 break;
10001 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010002 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010003 break;
10004 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -070010005 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010006 break;
10007 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +000010008 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010009 break;
10010 default:
10011 VIXL_UNIMPLEMENTED();
10012 break;
10013 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010014}
10015
10016void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -080010017 SimPRegister& pd = ReadPRegister(instr->GetPd());
10018 SimVRegister& zn = ReadVRegister(instr->GetRn());
10019 SimVRegister& zm = ReadVRegister(instr->GetRm());
10020 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10021 VectorFormat vform = instr->GetSVEVectorFormat();
10022 SimVRegister result;
10023
Martyn Capewell310a0822020-09-08 20:09:17 +010010024 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10025
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010026 switch (instr->Mask(SVEFPCompareVectorsMask)) {
10027 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010028 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010029 break;
10030 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010031 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010032 break;
10033 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010034 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010035 break;
10036 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010037 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010038 break;
10039 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010040 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010041 break;
10042 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010043 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010044 break;
10045 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -080010046 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010047 break;
10048 default:
10049 VIXL_UNIMPLEMENTED();
10050 break;
10051 }
TatWai Chong47c26842020-02-10 01:51:32 -080010052
10053 ExtractFromSimVRegister(vform, pd, result);
10054 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010055}
10056
10057void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -080010058 SimPRegister& pd = ReadPRegister(instr->GetPd());
10059 SimVRegister& zn = ReadVRegister(instr->GetRn());
10060 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10061 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chonge3775132020-02-16 22:13:17 -080010062
Martyn Capewell310a0822020-09-08 20:09:17 +010010063 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10064
10065 SimVRegister result;
TatWai Chonge3775132020-02-16 22:13:17 -080010066 SimVRegister zeros;
10067 dup_immediate(kFormatVnD, zeros, 0);
10068
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010069 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10070 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010071 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010072 break;
10073 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010074 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010075 break;
10076 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010077 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010078 break;
10079 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010080 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010081 break;
10082 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010083 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010084 break;
10085 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -080010086 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010087 break;
10088 default:
10089 VIXL_UNIMPLEMENTED();
10090 break;
10091 }
TatWai Chonge3775132020-02-16 22:13:17 -080010092
10093 ExtractFromSimVRegister(vform, pd, result);
10094 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010095}
10096
10097void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010098 VectorFormat vform = instr->GetSVEVectorFormat();
10099
10100 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10101 VIXL_UNIMPLEMENTED();
10102 }
10103
10104 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10105 SimVRegister& zm = ReadVRegister(instr->GetRn());
10106 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10107 int rot = instr->ExtractBit(16);
10108
10109 SimVRegister result;
10110
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010111 switch (instr->Mask(SVEFPComplexAdditionMask)) {
10112 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010113 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010114 break;
10115 default:
10116 VIXL_UNIMPLEMENTED();
10117 break;
10118 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +000010119 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010120}
10121
10122void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +010010123 VectorFormat vform = instr->GetSVEVectorFormat();
10124
10125 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10126 VIXL_UNIMPLEMENTED();
10127 }
10128
10129 SimVRegister& zda = ReadVRegister(instr->GetRd());
10130 SimVRegister& zn = ReadVRegister(instr->GetRn());
10131 SimVRegister& zm = ReadVRegister(instr->GetRm());
10132 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10133 int rot = instr->ExtractBits(14, 13);
10134
10135 SimVRegister result;
10136
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010137 switch (instr->Mask(SVEFPComplexMulAddMask)) {
10138 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +010010139 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010140 break;
10141 default:
10142 VIXL_UNIMPLEMENTED();
10143 break;
10144 }
Martyn Capewell75f1c432020-03-30 09:23:27 +010010145 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010146}
10147
10148void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +010010149 SimVRegister& zda = ReadVRegister(instr->GetRd());
10150 SimVRegister& zn = ReadVRegister(instr->GetRn());
10151 int rot = instr->ExtractBits(11, 10);
10152 unsigned zm_code = instr->GetRm();
10153 int index = -1;
10154 VectorFormat vform, vform_dup;
10155
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010156 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10157 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010158 vform = kFormatVnH;
10159 vform_dup = kFormatVnS;
10160 index = zm_code >> 3;
10161 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010162 break;
10163 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +010010164 vform = kFormatVnS;
10165 vform_dup = kFormatVnD;
10166 index = zm_code >> 4;
10167 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010168 break;
10169 default:
10170 VIXL_UNIMPLEMENTED();
10171 break;
10172 }
Martyn Capewelle4886e52020-03-30 09:28:52 +010010173
10174 if (index >= 0) {
10175 SimVRegister temp;
10176 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10177 fcmla(vform, zda, zn, temp, zda, rot);
10178 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010179}
10180
Martyn Capewell894962f2020-02-05 15:46:44 +000010181typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10182 LogicVRegister dst,
10183 const LogicVRegister& src);
10184
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010185void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +000010186 VectorFormat vform = instr->GetSVEVectorFormat();
10187 SimVRegister& vd = ReadVRegister(instr->GetRd());
10188 SimVRegister& zn = ReadVRegister(instr->GetRn());
10189 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10190 int lane_size = LaneSizeInBitsFromFormat(vform);
10191
10192 uint64_t inactive_value = 0;
10193 FastReduceFn fn = nullptr;
10194
Martyn Capewell310a0822020-09-08 20:09:17 +010010195 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10196
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010197 switch (instr->Mask(SVEFPFastReductionMask)) {
10198 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010199 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010200 break;
10201 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010202 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10203 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010204 break;
10205 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010206 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10207 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010208 break;
10209 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010210 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10211 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010212 break;
10213 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +000010214 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10215 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010216 break;
10217 default:
10218 VIXL_UNIMPLEMENTED();
10219 break;
10220 }
Martyn Capewell894962f2020-02-05 15:46:44 +000010221
10222 SimVRegister scratch;
10223 dup_immediate(vform, scratch, inactive_value);
10224 mov_merging(vform, scratch, pg, zn);
10225 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010226}
10227
10228void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +000010229 VectorFormat vform = kFormatUndefined;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010230
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010231 switch (instr->Mask(SVEFPMulIndexMask)) {
10232 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010233 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010234 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +000010235 case FMUL_z_zzi_h_i3h:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010236 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010237 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010238 break;
10239 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +000010240 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010241 break;
10242 default:
10243 VIXL_UNIMPLEMENTED();
10244 break;
10245 }
Martyn Capewell50e9f552020-01-07 17:45:03 +000010246
10247 SimVRegister& zd = ReadVRegister(instr->GetRd());
10248 SimVRegister& zn = ReadVRegister(instr->GetRn());
10249 SimVRegister temp;
10250
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010251 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
Martyn Capewell50e9f552020-01-07 17:45:03 +000010252 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010253}
10254
10255void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -080010256 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongf8d29f12020-02-16 22:53:18 -080010257 SimVRegister& zd = ReadVRegister(instr->GetRd());
10258 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10259 SimVRegister result;
10260
Martyn Capewell310a0822020-09-08 20:09:17 +010010261 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10262
TatWai Chongf8d29f12020-02-16 22:53:18 -080010263 if (instr->ExtractBit(15) == 0) {
10264 // Floating-point multiply-accumulate writing addend.
10265 SimVRegister& zm = ReadVRegister(instr->GetRm());
10266 SimVRegister& zn = ReadVRegister(instr->GetRn());
10267
10268 switch (instr->Mask(SVEFPMulAddMask)) {
10269 // zda = zda + zn * zm
10270 case FMLA_z_p_zzz:
10271 fmla(vform, result, zd, zn, zm);
10272 break;
10273 // zda = -zda + -zn * zm
10274 case FNMLA_z_p_zzz:
10275 fneg(vform, result, zd);
10276 fmls(vform, result, result, zn, zm);
10277 break;
10278 // zda = zda + -zn * zm
10279 case FMLS_z_p_zzz:
10280 fmls(vform, result, zd, zn, zm);
10281 break;
10282 // zda = -zda + zn * zm
10283 case FNMLS_z_p_zzz:
10284 fneg(vform, result, zd);
10285 fmla(vform, result, result, zn, zm);
10286 break;
10287 default:
10288 VIXL_UNIMPLEMENTED();
10289 break;
10290 }
10291 } else {
10292 // Floating-point multiply-accumulate writing multiplicand.
10293 SimVRegister& za = ReadVRegister(instr->GetRm());
10294 SimVRegister& zm = ReadVRegister(instr->GetRn());
10295
10296 switch (instr->Mask(SVEFPMulAddMask)) {
10297 // zdn = za + zdn * zm
10298 case FMAD_z_p_zzz:
10299 fmla(vform, result, za, zd, zm);
10300 break;
10301 // zdn = -za + -zdn * zm
10302 case FNMAD_z_p_zzz:
10303 fneg(vform, result, za);
10304 fmls(vform, result, result, zd, zm);
10305 break;
10306 // zdn = za + -zdn * zm
10307 case FMSB_z_p_zzz:
10308 fmls(vform, result, za, zd, zm);
10309 break;
10310 // zdn = -za + zdn * zm
10311 case FNMSB_z_p_zzz:
10312 fneg(vform, result, za);
10313 fmla(vform, result, result, zd, zm);
10314 break;
10315 default:
10316 VIXL_UNIMPLEMENTED();
10317 break;
10318 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010319 }
TatWai Chongf8d29f12020-02-16 22:53:18 -080010320
10321 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010322}
10323
10324void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010325 VectorFormat vform = kFormatUndefined;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010326
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010327 switch (instr->Mask(SVEFPMulAddIndexMask)) {
10328 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010329 case FMLS_z_zzzi_d:
10330 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010331 break;
10332 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010333 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010334 vform = kFormatVnS;
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010335 break;
10336 case FMLA_z_zzzi_h:
10337 case FMLS_z_zzzi_h:
10338 case FMLA_z_zzzi_h_i3h:
10339 case FMLS_z_zzzi_h_i3h:
10340 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010341 break;
10342 default:
10343 VIXL_UNIMPLEMENTED();
10344 break;
10345 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010346
10347 SimVRegister& zd = ReadVRegister(instr->GetRd());
10348 SimVRegister& zn = ReadVRegister(instr->GetRn());
10349 SimVRegister temp;
10350
Martyn Capewellf272b9c2020-11-05 18:30:16 +000010351 dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
TatWai Chonga2c1bb72020-02-16 23:16:47 -080010352 if (instr->ExtractBit(10) == 1) {
10353 fmls(vform, zd, zd, zn, temp);
10354 } else {
10355 fmla(vform, zd, zd, zn, temp);
10356 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010357}
10358
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010359void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -080010360 SimVRegister& zd = ReadVRegister(instr->GetRd());
10361 SimVRegister& zn = ReadVRegister(instr->GetRn());
10362 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10363 int dst_data_size;
10364 int src_data_size;
10365
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010366 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010367 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010368 case FCVTZU_z_p_z_d2w:
10369 dst_data_size = kSRegSize;
10370 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010371 break;
10372 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010373 case FCVTZU_z_p_z_d2x:
10374 dst_data_size = kDRegSize;
10375 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010376 break;
10377 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010378 case FCVTZU_z_p_z_fp162h:
10379 dst_data_size = kHRegSize;
10380 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010381 break;
10382 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010383 case FCVTZU_z_p_z_fp162w:
10384 dst_data_size = kSRegSize;
10385 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010386 break;
10387 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010388 case FCVTZU_z_p_z_fp162x:
10389 dst_data_size = kDRegSize;
10390 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010391 break;
10392 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010393 case FCVTZU_z_p_z_s2w:
10394 dst_data_size = kSRegSize;
10395 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010396 break;
10397 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010398 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -080010399 dst_data_size = kDRegSize;
10400 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010401 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010402 default:
10403 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -080010404 dst_data_size = 0;
10405 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010406 break;
10407 }
TatWai Chongdb7437c2020-01-09 17:44:10 -080010408
10409 VectorFormat vform =
10410 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -080010411
10412 if (instr->ExtractBit(16) == 0) {
10413 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10414 } else {
10415 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10416 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010417}
10418
10419void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -080010420 SimVRegister& zd = ReadVRegister(instr->GetRd());
10421 SimVRegister& zn = ReadVRegister(instr->GetRn());
10422 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10423 int dst_data_size;
10424 int src_data_size;
10425
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010426 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010427 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010428 dst_data_size = kHRegSize;
10429 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010430 break;
10431 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010432 dst_data_size = kSRegSize;
10433 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010434 break;
10435 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010436 dst_data_size = kDRegSize;
10437 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010438 break;
10439 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010440 dst_data_size = kSRegSize;
10441 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010442 break;
10443 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010444 dst_data_size = kDRegSize;
10445 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010446 break;
10447 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -080010448 dst_data_size = kHRegSize;
10449 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010450 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010451 default:
10452 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -080010453 dst_data_size = 0;
10454 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010455 break;
10456 }
TatWai Chong2cb1b612020-03-04 23:51:21 -080010457 VectorFormat vform =
10458 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10459
10460 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010461}
10462
10463void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010464 SimVRegister& zd = ReadVRegister(instr->GetRd());
10465 SimVRegister& zn = ReadVRegister(instr->GetRn());
10466 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10467 VectorFormat vform = instr->GetSVEVectorFormat();
10468 SimVRegister result;
10469
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010470 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010471 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010472 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010473 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010474 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -080010475 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010476 break;
10477 default:
10478 VIXL_UNIMPLEMENTED();
10479 break;
10480 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -080010481 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010482}
10483
10484void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010485 SimVRegister& zd = ReadVRegister(instr->GetRd());
10486 SimVRegister& zn = ReadVRegister(instr->GetRn());
10487 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10488 VectorFormat vform = instr->GetSVEVectorFormat();
10489 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10490 bool exact_exception = false;
10491
Martyn Capewell310a0822020-09-08 20:09:17 +010010492 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10493
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010494 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010495 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010496 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010497 break;
10498 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010499 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010500 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010501 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010502 break;
10503 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010504 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010505 break;
10506 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010507 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010508 break;
10509 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010510 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010511 break;
10512 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010513 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010514 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010515 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010516 VIXL_UNIMPLEMENTED();
10517 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010518 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -080010519
10520 SimVRegister result;
10521 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10522 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010523}
10524
10525void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -080010526 SimVRegister& zd = ReadVRegister(instr->GetRd());
10527 SimVRegister& zn = ReadVRegister(instr->GetRn());
10528 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10529 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10530 int dst_data_size;
10531 int src_data_size;
10532
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010533 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010534 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010535 case UCVTF_z_p_z_h2fp16:
10536 dst_data_size = kHRegSize;
10537 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010538 break;
10539 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010540 case UCVTF_z_p_z_w2d:
10541 dst_data_size = kDRegSize;
10542 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010543 break;
10544 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010545 case UCVTF_z_p_z_w2fp16:
10546 dst_data_size = kHRegSize;
10547 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010548 break;
10549 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010550 case UCVTF_z_p_z_w2s:
10551 dst_data_size = kSRegSize;
10552 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010553 break;
10554 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010555 case UCVTF_z_p_z_x2d:
10556 dst_data_size = kDRegSize;
10557 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010558 break;
10559 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010560 case UCVTF_z_p_z_x2fp16:
10561 dst_data_size = kHRegSize;
10562 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010563 break;
10564 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010565 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -080010566 dst_data_size = kSRegSize;
10567 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010568 break;
10569 default:
10570 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -080010571 dst_data_size = 0;
10572 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010573 break;
10574 }
TatWai Chong31cd6a02020-01-10 13:03:26 -080010575
10576 VectorFormat vform =
10577 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10578
10579 if (instr->ExtractBit(16) == 0) {
10580 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10581 } else {
10582 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10583 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010584}
10585
10586void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +000010587 VectorFormat vform = instr->GetSVEVectorFormat();
10588 SimVRegister& zd = ReadVRegister(instr->GetRd());
10589 SimVRegister& zn = ReadVRegister(instr->GetRn());
10590 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10591
Martyn Capewell310a0822020-09-08 20:09:17 +010010592 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10593
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010594 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10595 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010596 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010597 break;
10598 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +000010599 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010600 break;
10601 default:
10602 VIXL_UNIMPLEMENTED();
10603 break;
10604 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010605}
10606
10607void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010608 VectorFormat vform = instr->GetSVEVectorFormat();
10609 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10610
10611 int count = CountActiveLanes(vform, pg);
10612
10613 if (instr->ExtractBit(11) == 0) {
10614 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10615 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10616 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010617 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010618 break;
10619 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010620 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010621 break;
10622 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010623 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010624 break;
10625 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010626 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010627 break;
10628 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010629 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010630 break;
10631 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +010010632 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010633 break;
10634 default:
10635 VIXL_UNIMPLEMENTED();
10636 break;
10637 }
10638 } else {
10639 bool is_saturating = (instr->ExtractBit(18) == 0);
10640 bool decrement =
10641 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10642 bool is_signed = (instr->ExtractBit(16) == 0);
10643 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10644 unsigned width = sf ? kXRegSize : kWRegSize;
10645
10646 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10647 case DECP_r_p_r:
10648 case INCP_r_p_r:
10649 case SQDECP_r_p_r_sx:
10650 case SQDECP_r_p_r_x:
10651 case SQINCP_r_p_r_sx:
10652 case SQINCP_r_p_r_x:
10653 case UQDECP_r_p_r_uw:
10654 case UQDECP_r_p_r_x:
10655 case UQINCP_r_p_r_uw:
10656 case UQINCP_r_p_r_x:
10657 WriteXRegister(instr->GetRd(),
10658 IncDecN(ReadXRegister(instr->GetRd()),
10659 decrement ? -count : count,
10660 width,
10661 is_saturating,
10662 is_signed));
10663 break;
10664 default:
10665 VIXL_UNIMPLEMENTED();
10666 break;
10667 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010668 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010669}
10670
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010671uint64_t Simulator::IncDecN(uint64_t acc,
10672 int64_t delta,
10673 unsigned n,
10674 bool is_saturating,
10675 bool is_signed) {
10676 VIXL_ASSERT(n <= 64);
10677 VIXL_ASSERT(IsIntN(n, delta));
10678
10679 uint64_t sign_mask = UINT64_C(1) << (n - 1);
10680 uint64_t mask = GetUintMask(n);
10681
10682 acc &= mask; // Ignore initial accumulator high bits.
10683 uint64_t result = (acc + delta) & mask;
10684
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010685 bool result_negative = ((result & sign_mask) != 0);
10686
10687 if (is_saturating) {
10688 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +000010689 bool acc_negative = ((acc & sign_mask) != 0);
10690 bool delta_negative = delta < 0;
10691
Jacob Bramleyd1686cb2019-05-28 17:39:05 +010010692 // If the signs of the operands are the same, but different from the
10693 // result, there was an overflow.
10694 if ((acc_negative == delta_negative) &&
10695 (acc_negative != result_negative)) {
10696 if (result_negative) {
10697 // Saturate to [..., INT<n>_MAX].
10698 result_negative = false;
10699 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
10700 } else {
10701 // Saturate to [INT<n>_MIN, ...].
10702 result_negative = true;
10703 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
10704 }
10705 }
10706 } else {
10707 if ((delta < 0) && (result > acc)) {
10708 // Saturate to [0, ...].
10709 result = 0;
10710 } else if ((delta > 0) && (result < acc)) {
10711 // Saturate to [..., UINT<n>_MAX].
10712 result = mask;
10713 }
10714 }
10715 }
10716
10717 // Sign-extend if necessary.
10718 if (result_negative && is_signed) result |= ~mask;
10719
10720 return result;
10721}
10722
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010723void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010724 VectorFormat vform = instr->GetSVEVectorFormat();
10725 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010726 switch (instr->Mask(SVEIndexGenerationMask)) {
10727 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010728 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010729 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010730 case INDEX_z_rr: {
10731 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10732 : instr->ExtractSignedBits(9, 5);
10733 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10734 : instr->ExtractSignedBits(20, 16);
10735 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010736 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +010010737 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010738 default:
10739 VIXL_UNIMPLEMENTED();
10740 break;
10741 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010742}
10743
10744void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -070010745 VectorFormat vform = instr->GetSVEVectorFormat();
10746 SimVRegister& zd = ReadVRegister(instr->GetRd());
10747 SimVRegister& zn = ReadVRegister(instr->GetRn());
10748 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010749 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10750 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010751 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010752 break;
10753 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010754 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010755 break;
10756 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010757 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010758 break;
10759 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010760 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010761 break;
10762 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010763 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010764 break;
10765 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -070010766 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010767 break;
10768 default:
10769 VIXL_UNIMPLEMENTED();
10770 break;
10771 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010772}
10773
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010774void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010775 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -070010776 VectorFormat vform = instr->GetSVEVectorFormat();
10777 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10778 SimVRegister& zm = ReadVRegister(instr->GetRn());
10779 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10780 SimVRegister result;
10781
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010782 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010783 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010784 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010785 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010786 case SUBR_z_p_zz:
10787 sub(vform, result, zm, zdn);
10788 break;
10789 case SUB_z_p_zz:
10790 sub(vform, result, zdn, zm);
10791 break;
10792 default:
10793 VIXL_UNIMPLEMENTED();
10794 break;
10795 }
10796 mov_merging(vform, zdn, pg, result);
10797}
10798
10799void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10800 VectorFormat vform = instr->GetSVEVectorFormat();
10801 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10802 SimVRegister& zm = ReadVRegister(instr->GetRn());
10803 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10804 SimVRegister result;
10805
10806 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010807 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010808 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010809 break;
10810 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010811 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010812 break;
10813 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010814 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010815 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010816 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010817 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010818 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010819 default:
10820 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010821 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010822 }
10823 mov_merging(vform, zdn, pg, result);
10824}
10825
10826void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10827 VectorFormat vform = instr->GetSVEVectorFormat();
10828 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10829 SimVRegister& zm = ReadVRegister(instr->GetRn());
10830 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10831 SimVRegister result;
10832
10833 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10834 case MUL_z_p_zz:
10835 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010836 break;
10837 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010838 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010839 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010840 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -070010841 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010842 break;
10843 default:
10844 VIXL_UNIMPLEMENTED();
10845 break;
10846 }
TatWai Chong13634762019-07-16 16:20:45 -070010847 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010848}
10849
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010850void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10851 const Instruction* instr) {
10852 VectorFormat vform = instr->GetSVEVectorFormat();
10853 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10854 SimVRegister& zm = ReadVRegister(instr->GetRn());
10855 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10856 SimVRegister result;
10857
10858 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10859 case SABD_z_p_zz:
10860 absdiff(vform, result, zdn, zm, true);
10861 break;
10862 case SMAX_z_p_zz:
10863 smax(vform, result, zdn, zm);
10864 break;
10865 case SMIN_z_p_zz:
10866 smin(vform, result, zdn, zm);
10867 break;
10868 case UABD_z_p_zz:
10869 absdiff(vform, result, zdn, zm, false);
10870 break;
10871 case UMAX_z_p_zz:
10872 umax(vform, result, zdn, zm);
10873 break;
10874 case UMIN_z_p_zz:
10875 umin(vform, result, zdn, zm);
10876 break;
10877 default:
10878 VIXL_UNIMPLEMENTED();
10879 break;
10880 }
10881 mov_merging(vform, zdn, pg, result);
10882}
10883
10884void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10885 VectorFormat vform = instr->GetSVEVectorFormat();
10886 SimVRegister& zd = ReadVRegister(instr->GetRd());
10887 SimVRegister scratch;
10888
10889 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10890 case MUL_z_zi:
10891 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10892 mul(vform, zd, zd, scratch);
10893 break;
10894 default:
10895 VIXL_UNIMPLEMENTED();
10896 break;
10897 }
10898}
10899
10900void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10901 VectorFormat vform = instr->GetSVEVectorFormat();
10902 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10903 SimVRegister& zm = ReadVRegister(instr->GetRn());
10904 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10905 SimVRegister result;
10906
10907 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10908
10909 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10910 case SDIVR_z_p_zz:
10911 sdiv(vform, result, zm, zdn);
10912 break;
10913 case SDIV_z_p_zz:
10914 sdiv(vform, result, zdn, zm);
10915 break;
10916 case UDIVR_z_p_zz:
10917 udiv(vform, result, zm, zdn);
10918 break;
10919 case UDIV_z_p_zz:
10920 udiv(vform, result, zdn, zm);
10921 break;
10922 default:
10923 VIXL_UNIMPLEMENTED();
10924 break;
10925 }
10926 mov_merging(vform, zdn, pg, result);
10927}
10928
10929void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10930 VectorFormat vform = instr->GetSVEVectorFormat();
10931 SimVRegister& zd = ReadVRegister(instr->GetRd());
10932 SimVRegister scratch;
10933
10934 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10935 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10936
10937 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10938 case SMAX_z_zi:
10939 dup_immediate(vform, scratch, signed_imm);
10940 smax(vform, zd, zd, scratch);
10941 break;
10942 case SMIN_z_zi:
10943 dup_immediate(vform, scratch, signed_imm);
10944 smin(vform, zd, zd, scratch);
10945 break;
10946 case UMAX_z_zi:
10947 dup_immediate(vform, scratch, unsigned_imm);
10948 umax(vform, zd, zd, scratch);
10949 break;
10950 case UMIN_z_zi:
10951 dup_immediate(vform, scratch, unsigned_imm);
10952 umin(vform, zd, zd, scratch);
10953 break;
10954 default:
10955 VIXL_UNIMPLEMENTED();
10956 break;
10957 }
10958}
10959
10960void Simulator::VisitSVEIntCompareScalarCountAndLimit(
10961 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -070010962 unsigned rn_code = instr->GetRn();
10963 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010964 SimPRegister& pd = ReadPRegister(instr->GetPd());
10965 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chongc844bb22019-06-10 15:32:53 -070010966
Martyn Capewellf0844012020-10-23 16:38:26 +010010967 bool is_64_bit = instr->ExtractBit(12) == 1;
10968 int rsize = is_64_bit ? kXRegSize : kWRegSize;
10969 uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
10970
10971 uint64_t usrc1 = ReadXRegister(rn_code);
10972 int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
10973 uint64_t usrc2 = ssrc2 & mask;
10974
10975 bool reverse = (form_hash_ == Hash("whilege_p_p_rr")) ||
10976 (form_hash_ == Hash("whilegt_p_p_rr")) ||
10977 (form_hash_ == Hash("whilehi_p_p_rr")) ||
10978 (form_hash_ == Hash("whilehs_p_p_rr"));
10979
10980 int lane_count = LaneCountFromFormat(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010981 bool last = true;
Martyn Capewellf0844012020-10-23 16:38:26 +010010982 for (int i = 0; i < lane_count; i++) {
10983 usrc1 &= mask;
10984 int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
10985
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010986 bool cond = false;
Martyn Capewellf0844012020-10-23 16:38:26 +010010987 switch (form_hash_) {
10988 case Hash("whilele_p_p_rr"):
10989 cond = ssrc1 <= ssrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070010990 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010991 case Hash("whilelo_p_p_rr"):
10992 cond = usrc1 < usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010993 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010994 case Hash("whilels_p_p_rr"):
10995 cond = usrc1 <= usrc2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010996 break;
Martyn Capewellf0844012020-10-23 16:38:26 +010010997 case Hash("whilelt_p_p_rr"):
10998 cond = ssrc1 < ssrc2;
10999 break;
11000 case Hash("whilege_p_p_rr"):
11001 cond = ssrc1 >= ssrc2;
11002 break;
11003 case Hash("whilegt_p_p_rr"):
11004 cond = ssrc1 > ssrc2;
11005 break;
11006 case Hash("whilehi_p_p_rr"):
11007 cond = usrc1 > usrc2;
11008 break;
11009 case Hash("whilehs_p_p_rr"):
11010 cond = usrc1 >= usrc2;
TatWai Chongc844bb22019-06-10 15:32:53 -070011011 break;
11012 default:
TatWai Chongc844bb22019-06-10 15:32:53 -070011013 VIXL_UNIMPLEMENTED();
11014 break;
11015 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011016 last = last && cond;
11017 LogicPRegister dst(pd);
Martyn Capewellf0844012020-10-23 16:38:26 +010011018 int lane = reverse ? ((lane_count - 1) - i) : i;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011019 dst.SetActive(vform, lane, last);
Martyn Capewellf0844012020-10-23 16:38:26 +010011020 usrc1 += reverse ? -1 : 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011021 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011022
11023 PredTest(vform, GetPTrue(), pd);
11024 LogSystemRegister(NZCV);
11025}
11026
11027void Simulator::VisitSVEConditionallyTerminateScalars(
11028 const Instruction* instr) {
11029 unsigned rn_code = instr->GetRn();
11030 unsigned rm_code = instr->GetRm();
11031 bool is_64_bit = instr->ExtractBit(22) == 1;
11032 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
11033 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11034 bool term;
11035 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
11036 case CTERMEQ_rr:
11037 term = src1 == src2;
11038 break;
11039 case CTERMNE_rr:
11040 term = src1 != src2;
11041 break;
11042 default:
11043 term = false;
11044 VIXL_UNIMPLEMENTED();
11045 break;
11046 }
11047 ReadNzcv().SetN(term ? 1 : 0);
11048 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -070011049 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011050}
11051
11052void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011053 bool commute_inputs = false;
11054 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011055 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11056 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011057 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011058 break;
11059 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011060 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011061 break;
11062 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011063 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011064 break;
11065 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011066 cond = ge;
11067 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011068 break;
11069 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011070 cond = gt;
11071 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011072 break;
11073 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011074 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011075 break;
11076 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011077 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011078 VIXL_UNIMPLEMENTED();
11079 break;
11080 }
TatWai Chong302729c2019-06-14 16:18:51 -070011081
11082 VectorFormat vform = instr->GetSVEVectorFormat();
11083 SimVRegister src2;
11084 dup_immediate(vform,
11085 src2,
11086 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11087 SVEIntCompareVectorsHelper(cond,
11088 vform,
11089 ReadPRegister(instr->GetPd()),
11090 ReadPRegister(instr->GetPgLow8()),
11091 commute_inputs ? src2
11092 : ReadVRegister(instr->GetRn()),
11093 commute_inputs ? ReadVRegister(instr->GetRn())
11094 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011095}
11096
11097void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -070011098 bool commute_inputs = false;
11099 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011100 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11101 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011102 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011103 break;
11104 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011105 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011106 break;
11107 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011108 cond = hi;
11109 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011110 break;
11111 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -070011112 cond = hs;
11113 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011114 break;
11115 default:
TatWai Chong302729c2019-06-14 16:18:51 -070011116 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011117 VIXL_UNIMPLEMENTED();
11118 break;
11119 }
TatWai Chong302729c2019-06-14 16:18:51 -070011120
11121 VectorFormat vform = instr->GetSVEVectorFormat();
11122 SimVRegister src2;
11123 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11124 SVEIntCompareVectorsHelper(cond,
11125 vform,
11126 ReadPRegister(instr->GetPd()),
11127 ReadPRegister(instr->GetPgLow8()),
11128 commute_inputs ? src2
11129 : ReadVRegister(instr->GetRn()),
11130 commute_inputs ? ReadVRegister(instr->GetRn())
11131 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011132}
11133
11134void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -070011135 Instr op = instr->Mask(SVEIntCompareVectorsMask);
11136 bool is_wide_elements = false;
11137 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011138 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -070011139 case CMPGE_p_p_zw:
11140 case CMPGT_p_p_zw:
11141 case CMPHI_p_p_zw:
11142 case CMPHS_p_p_zw:
11143 case CMPLE_p_p_zw:
11144 case CMPLO_p_p_zw:
11145 case CMPLS_p_p_zw:
11146 case CMPLT_p_p_zw:
11147 case CMPNE_p_p_zw:
11148 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011149 break;
TatWai Chong96713fe2019-06-04 16:39:37 -070011150 }
11151
TatWai Chong302729c2019-06-14 16:18:51 -070011152 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -070011153 switch (op) {
11154 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011155 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011156 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011157 break;
11158 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011159 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011160 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011161 break;
11162 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011163 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011164 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011165 break;
11166 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011167 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011168 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011169 break;
11170 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011171 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011172 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011173 break;
11174 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011175 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -070011176 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -070011177 break;
11178 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011179 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -070011180 break;
11181 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011182 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -070011183 break;
11184 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011185 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -070011186 break;
11187 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -070011188 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011189 break;
11190 default:
11191 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -070011192 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011193 break;
11194 }
TatWai Chong96713fe2019-06-04 16:39:37 -070011195
TatWai Chong302729c2019-06-14 16:18:51 -070011196 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -070011197 instr->GetSVEVectorFormat(),
11198 ReadPRegister(instr->GetPd()),
11199 ReadPRegister(instr->GetPgLow8()),
11200 ReadVRegister(instr->GetRn()),
11201 ReadVRegister(instr->GetRm()),
11202 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011203}
11204
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011205void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011206 VectorFormat vform = instr->GetSVEVectorFormat();
11207 SimVRegister& zd = ReadVRegister(instr->GetRd());
11208 SimVRegister& zn = ReadVRegister(instr->GetRn());
11209
11210 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11211 (vform == kFormatVnD));
11212
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011213 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011214 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +000011215 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011216 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011217 default:
11218 VIXL_UNIMPLEMENTED();
11219 break;
11220 }
11221}
11222
11223void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +000011224 VectorFormat vform = instr->GetSVEVectorFormat();
11225 SimVRegister& zd = ReadVRegister(instr->GetRd());
11226 SimVRegister& zn = ReadVRegister(instr->GetRn());
11227 SimVRegister& zm = ReadVRegister(instr->GetRm());
11228
11229 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11230 (vform == kFormatVnD));
11231
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011232 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011233 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +000011234 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011235 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011236 default:
11237 VIXL_UNIMPLEMENTED();
11238 break;
11239 }
11240}
11241
11242void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11243 const Instruction* instr) {
11244 SimVRegister& zd = ReadVRegister(instr->GetRd());
11245 SimVRegister& zn = ReadVRegister(instr->GetRn());
11246
11247 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011248 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011249 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11250 // Record the movprfx, so the next ExecuteInstruction() can check it.
11251 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011252 break;
11253 default:
11254 VIXL_UNIMPLEMENTED();
11255 break;
11256 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011257}
11258
11259void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +010011260 VectorFormat vform = instr->GetSVEVectorFormat();
11261
11262 SimVRegister& zd = ReadVRegister(instr->GetRd());
11263 SimVRegister& zm = ReadVRegister(instr->GetRm());
11264
11265 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011266 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011267 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011268 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011269 break;
11270 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +010011271 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011272 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011273 case MAD_z_p_zzz:
11274 // 'za' is encoded in 'Rn'.
11275 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011276 break;
Jacob Bramley22023df2019-05-14 17:55:43 +010011277 case MSB_z_p_zzz: {
11278 // 'za' is encoded in 'Rn'.
11279 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11280 break;
11281 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011282 default:
11283 VIXL_UNIMPLEMENTED();
11284 break;
11285 }
Jacob Bramley22023df2019-05-14 17:55:43 +010011286 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011287}
11288
11289void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011290 VectorFormat vform = instr->GetSVEVectorFormat();
11291 SimVRegister& zda = ReadVRegister(instr->GetRd());
11292 SimVRegister& zn = ReadVRegister(instr->GetRn());
11293 SimVRegister& zm = ReadVRegister(instr->GetRm());
11294
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011295 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
11296 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011297 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011298 break;
11299 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -070011300 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011301 break;
11302 default:
11303 VIXL_UNIMPLEMENTED();
11304 break;
11305 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011306}
11307
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011308void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011309 VectorFormat vform = instr->GetSVEVectorFormat();
11310 SimVRegister& zn = ReadVRegister(instr->GetRn());
11311 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11312 SimVRegister& zd = ReadVRegister(instr->GetRd());
11313
11314 switch (instr->Mask(SVEMovprfxMask)) {
11315 case MOVPRFX_z_p_z:
11316 if (instr->ExtractBit(16)) {
11317 mov_merging(vform, zd, pg, zn);
11318 } else {
11319 mov_zeroing(vform, zd, pg, zn);
11320 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011321
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011322 // Record the movprfx, so the next ExecuteInstruction() can check it.
11323 movprfx_ = instr;
11324 break;
11325 default:
11326 VIXL_UNIMPLEMENTED();
11327 break;
11328 }
11329}
11330
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011331void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011332 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +010011333 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011334 SimVRegister& zn = ReadVRegister(instr->GetRn());
11335 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11336
11337 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11338 switch (instr->Mask(SVEIntReductionLogicalMask)) {
11339 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011340 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011341 break;
11342 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011343 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011344 break;
11345 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +010011346 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011347 break;
11348 default:
11349 VIXL_UNIMPLEMENTED();
11350 break;
11351 }
11352 } else {
11353 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011354 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011355 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011356 break;
11357 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011358 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011359 break;
11360 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011361 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011362 break;
11363 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011364 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011365 break;
11366 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011367 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011368 break;
11369 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -070011370 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010011371 break;
11372 default:
11373 VIXL_UNIMPLEMENTED();
11374 break;
11375 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011376 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011377}
11378
11379void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011380 VectorFormat vform = instr->GetSVEVectorFormat();
11381 SimVRegister& zn = ReadVRegister(instr->GetRn());
11382
11383 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011384 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11385 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011386 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011387 break;
11388 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011389 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011390 break;
11391 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011392 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011393 break;
11394 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011395 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011396 break;
11397 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011398 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011399 break;
11400 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011401 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011402 break;
11403 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011404 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011405 break;
11406 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011407 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011408 break;
11409 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011410 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011411 break;
11412 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011413 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011414 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011415 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011416 break;
11417 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011418 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011419 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011420 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011421 break;
11422 default:
11423 VIXL_UNIMPLEMENTED();
11424 break;
11425 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +010011426
11427 SimVRegister& zd = ReadVRegister(instr->GetRd());
11428 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11429 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011430}
11431
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011432void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011433 // There is only one instruction in this group.
11434 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11435
11436 VectorFormat vform = instr->GetSVEVectorFormat();
11437 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11438 SimVRegister& zd = ReadVRegister(instr->GetRd());
11439
Martyn Capewell310a0822020-09-08 20:09:17 +010011440 if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11441
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011442 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011443 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011444 case FCPY_z_p_i: {
11445 int imm8 = instr->ExtractBits(12, 5);
11446 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11447 Instruction::Imm8ToFP64(imm8));
11448 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011449 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011450 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011451 default:
11452 VIXL_UNIMPLEMENTED();
11453 break;
11454 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011455 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011456}
11457
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011458void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11459 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +010011460 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010011461 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +010011462 SimVRegister scratch;
11463
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011464 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11465 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011466
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011467 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011468 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011469 add_uint(vform, zd, zd, imm);
11470 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011471 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011472 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11473 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011474 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011475 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11476 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011477 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011478 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +010011479 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011480 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011481 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011482 sub_uint(vform, zd, zd, imm);
11483 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011484 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011485 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11486 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011487 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011488 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11489 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011490 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011491 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +010011492 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011493}
TatWai Chong6995bfd2019-09-26 10:48:05 +010011494
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011495void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11496 SimVRegister& zd = ReadVRegister(instr->GetRd());
11497
Martyn Capewell8ed83522020-08-11 16:19:43 +010011498 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011499 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +010011500 int shift = instr->ExtractBit(13) * 8;
11501 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011502
11503 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11504 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +010011505 // The encoding of byte-sized lanes with lsl #8 is undefined.
11506 if ((format == kFormatVnB) && (shift == 8)) {
11507 VIXL_UNIMPLEMENTED();
11508 } else {
11509 dup_immediate(format, zd, imm);
11510 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011511 break;
11512 default:
11513 VIXL_UNIMPLEMENTED();
11514 break;
11515 }
11516}
11517
11518void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11519 VectorFormat vform = instr->GetSVEVectorFormat();
11520 SimVRegister& zd = ReadVRegister(instr->GetRd());
11521
11522 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011523 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +010011524 switch (vform) {
11525 case kFormatVnH:
11526 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11527 break;
11528 case kFormatVnS:
11529 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11530 break;
11531 case kFormatVnD:
11532 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11533 break;
11534 default:
11535 VIXL_UNIMPLEMENTED();
11536 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011537 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011538 default:
11539 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011540 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011541 }
11542}
11543
11544void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11545 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011546 switch (instr->Mask(
11547 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11548 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011549 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011550 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011551 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011552 break;
11553 default:
11554 VIXL_UNIMPLEMENTED();
11555 break;
11556 }
TatWai Chong113d9192020-05-19 01:02:36 -070011557
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011558 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11559 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011560}
11561
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011562void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011563 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011564 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11565 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011566 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011567 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011568 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011569 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011570 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011571 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011572 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011573 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011574 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011575 break;
11576 default:
11577 VIXL_UNIMPLEMENTED();
11578 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011579 }
TatWai Chong113d9192020-05-19 01:02:36 -070011580
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011581 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11582 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011583}
11584
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011585void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11586 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011587 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11588 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011589 VIXL_UNIMPLEMENTED();
11590 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011591 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011592 VIXL_UNIMPLEMENTED();
11593 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011594 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011595 VIXL_UNIMPLEMENTED();
11596 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011597 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011598 VIXL_UNIMPLEMENTED();
11599 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011600 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011601 VIXL_UNIMPLEMENTED();
11602 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011603 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011604 VIXL_UNIMPLEMENTED();
11605 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011606 case LDFF1H_z_p_ai_s:
11607 VIXL_UNIMPLEMENTED();
11608 break;
11609 case LDFF1SB_z_p_ai_s:
11610 VIXL_UNIMPLEMENTED();
11611 break;
11612 case LDFF1SH_z_p_ai_s:
11613 VIXL_UNIMPLEMENTED();
11614 break;
11615 case LDFF1W_z_p_ai_s:
11616 VIXL_UNIMPLEMENTED();
11617 break;
11618 default:
11619 VIXL_UNIMPLEMENTED();
11620 break;
11621 }
11622}
11623
11624void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11625 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011626 switch (
11627 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11628 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011629 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011630 break;
11631 default:
11632 VIXL_UNIMPLEMENTED();
11633 break;
11634 }
TatWai Chong113d9192020-05-19 01:02:36 -070011635
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011636 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11637 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011638}
11639
11640void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11641 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011642 switch (
11643 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011644 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011645 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011646 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011647 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011648 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011649 break;
11650 default:
11651 VIXL_UNIMPLEMENTED();
11652 break;
11653 }
11654}
11655
11656void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11657 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011658 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011659 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011660 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011661 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011662 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011663 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011664 break;
11665 default:
11666 VIXL_UNIMPLEMENTED();
11667 break;
11668 }
11669}
11670
11671void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11672 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011673 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011674 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011675 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011676 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011677 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011678 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011679 break;
11680 default:
11681 VIXL_UNIMPLEMENTED();
11682 break;
11683 }
11684}
11685
11686void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11687 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011688 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011689 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011690 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011691 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011692 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011693 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +010011694 if (instr->GetRm() == kZeroRegCode) {
11695 VIXL_UNIMPLEMENTED();
11696 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011697 break;
11698 default:
11699 VIXL_UNIMPLEMENTED();
11700 break;
11701 }
11702}
11703
11704void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -070011705 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011706 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011707 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -070011708 case LD1RB_z_p_bi_u16:
11709 case LD1RB_z_p_bi_u32:
11710 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011711 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011712 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011713 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -070011714 case LD1RW_z_p_bi_u32:
11715 case LD1RW_z_p_bi_u64:
11716 case LD1RD_z_p_bi_u64:
11717 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011718 break;
11719 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011720 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011721 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011722 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011723 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011724 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -070011725 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011726 break;
11727 default:
TatWai Chong85e15102020-05-04 21:00:40 -070011728 // This encoding group is complete, so no other values should be possible.
11729 VIXL_UNREACHABLE();
11730 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011731 break;
11732 }
TatWai Chong85e15102020-05-04 21:00:40 -070011733
11734 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11735 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11736 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11737 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11738 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11739 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11740 VectorFormat unpack_vform =
11741 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11742 SimVRegister temp;
11743 ld1r(vform, unpack_vform, temp, base, is_signed);
11744 mov_zeroing(vform,
11745 ReadVRegister(instr->GetRt()),
11746 ReadPRegister(instr->GetPgLow8()),
11747 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011748}
11749
11750void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11751 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11752 case LDR_p_bi: {
11753 SimPRegister& pt = ReadPRegister(instr->GetPt());
11754 int pl = GetPredicateLengthInBytes();
11755 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11756 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11757 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11758 for (int i = 0; i < pl; i++) {
11759 pt.Insert(i, Memory::Read<uint8_t>(address + i));
11760 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011761 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011762 break;
11763 }
11764 default:
11765 VIXL_UNIMPLEMENTED();
11766 break;
11767 }
11768}
11769
11770void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011771 switch (instr->Mask(SVELoadVectorRegisterMask)) {
11772 case LDR_z_bi: {
11773 SimVRegister& zt = ReadVRegister(instr->GetRt());
11774 int vl = GetVectorLengthInBytes();
11775 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11776 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11777 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11778 for (int i = 0; i < vl; i++) {
11779 zt.Insert(i, Memory::Read<uint8_t>(address + i));
11780 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000011781 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011782 break;
11783 }
11784 default:
11785 VIXL_UNIMPLEMENTED();
11786 break;
11787 }
11788}
11789
11790void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11791 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011792 switch (instr->Mask(
11793 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011794 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011795 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011796 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011797 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011798 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011799 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011800 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011801 case LDFF1D_z_p_bz_d_x32_scaled:
11802 case LDFF1SH_z_p_bz_d_x32_scaled:
11803 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011804 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011805 default:
11806 VIXL_UNIMPLEMENTED();
11807 break;
11808 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011809
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011810 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11811 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011812}
11813
11814void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11815 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011816 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11817 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011818 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011819 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011820 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011821 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011822 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011823 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011824 case LDFF1D_z_p_bz_d_64_scaled:
11825 case LDFF1SH_z_p_bz_d_64_scaled:
11826 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011827 break;
11828 default:
11829 VIXL_UNIMPLEMENTED();
11830 break;
11831 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011832
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011833 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011834}
11835
11836void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11837 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011838 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11839 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011840 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011841 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011842 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011843 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011844 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011845 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011846 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011847 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011848 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011849 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011850 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011851 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011852 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011853 break;
11854 default:
11855 VIXL_UNIMPLEMENTED();
11856 break;
11857 }
TatWai Chong113d9192020-05-19 01:02:36 -070011858
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011859 SVEGatherLoadScalarPlusVectorHelper(instr,
11860 kFormatVnD,
11861 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011862}
11863
11864void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11865 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011866 switch (instr->Mask(
11867 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11868 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011869 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011870 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011871 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011872 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011873 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011874 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011875 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011876 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011877 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -070011878 case LDFF1D_z_p_bz_d_x32_unscaled:
11879 case LDFF1SB_z_p_bz_d_x32_unscaled:
11880 case LDFF1SH_z_p_bz_d_x32_unscaled:
11881 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011882 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011883 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011884 VIXL_UNIMPLEMENTED();
11885 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011886 }
TatWai Chong1af34f12020-06-01 20:54:06 -070011887
TatWai Chongcd3f6c52020-06-14 00:42:39 -070011888 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11889 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011890}
11891
11892void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11893 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011894 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11895 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011896 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011897 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011898 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011899 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011900 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011901 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011902 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011903 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011904 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011905 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011906 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011907 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011908 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011909 break;
11910 default:
11911 VIXL_UNIMPLEMENTED();
11912 break;
11913 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +000011914 bool is_signed = instr->ExtractBit(14) == 0;
11915 bool is_ff = instr->ExtractBit(13) == 1;
11916 // Note that these instructions don't use the Dtype encoding.
11917 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11918 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11919 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11920 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11921 if (is_ff) {
11922 VIXL_UNIMPLEMENTED();
11923 } else {
11924 SVEStructuredLoadHelper(kFormatVnD,
11925 ReadPRegister(instr->GetPgLow8()),
11926 instr->GetRt(),
11927 addr,
11928 is_signed);
11929 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011930}
11931
11932void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11933 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011934 switch (
11935 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011936 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011937 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011938 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011939 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011940 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011941 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011942 default:
11943 VIXL_UNIMPLEMENTED();
11944 break;
11945 }
11946}
11947
11948void Simulator::
11949 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
11950 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011951 switch (instr->Mask(
11952 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011953 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011954 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011955 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011956 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011957 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011958 break;
11959 default:
11960 VIXL_UNIMPLEMENTED();
11961 break;
11962 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011963}
11964
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011965void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
11966 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011967 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -070011968 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011969 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011970 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011971 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011972 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011973 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011974 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011975 VIXL_UNIMPLEMENTED();
11976 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011977 }
11978}
11979
11980void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
11981 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +000011982 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +000011983 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011984 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011985 case LDFF1B_z_p_br_u16:
11986 case LDFF1B_z_p_br_u32:
11987 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011988 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011989 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011990 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000011991 case LDFF1W_z_p_br_u32:
11992 case LDFF1W_z_p_br_u64:
11993 case LDFF1D_z_p_br_u64:
11994 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011995 break;
11996 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011997 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011998 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011999 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012000 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012001 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012002 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012003 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012004 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +000012005 // This encoding group is complete, so no other values should be possible.
12006 VIXL_UNREACHABLE();
12007 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012008 break;
12009 }
Jacob Bramley85a9c102019-12-09 17:48:29 +000012010
12011 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12012 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12013 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12014 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12015 uint64_t offset = ReadXRegister(instr->GetRm());
12016 offset <<= msize_in_bytes_log2;
12017 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12018 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12019 SVEFaultTolerantLoadHelper(vform,
12020 ReadPRegister(instr->GetPgLow8()),
12021 instr->GetRt(),
12022 addr,
12023 kSVEFirstFaultLoad,
12024 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012025}
12026
12027void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
12028 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012029 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012030 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012031 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012032 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012033 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012034 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012035 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012036 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012037 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012038 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012039 case LDNF1W_z_p_bi_u32:
12040 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012041 break;
12042 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012043 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012044 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012045 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012046 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012047 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012048 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012049 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012050 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012051 VIXL_UNIMPLEMENTED();
12052 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012053 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000012054 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12055 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12056 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12057 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12058 int vl = GetVectorLengthInBytes();
12059 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12060 uint64_t offset =
12061 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12062 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12063 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12064 SVEFaultTolerantLoadHelper(vform,
12065 ReadPRegister(instr->GetPgLow8()),
12066 instr->GetRt(),
12067 addr,
12068 kSVENonFaultLoad,
12069 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012070}
12071
12072void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12073 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012074 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12075 VectorFormat vform = kFormatUndefined;
12076
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012077 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12078 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012079 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012080 break;
12081 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012082 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012083 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012084 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012085 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012086 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012087 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012088 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012089 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012090 default:
12091 VIXL_UNIMPLEMENTED();
12092 break;
12093 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012094 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12095 int vl = GetVectorLengthInBytes();
12096 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12097 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12098 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12099 SVEStructuredLoadHelper(vform,
12100 pg,
12101 instr->GetRt(),
12102 addr,
12103 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012104}
12105
12106void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12107 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000012108 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12109 VectorFormat vform = kFormatUndefined;
12110
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012111 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12112 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012113 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012114 break;
12115 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012116 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012117 break;
12118 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012119 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012120 break;
12121 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000012122 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012123 break;
12124 default:
12125 VIXL_UNIMPLEMENTED();
12126 break;
12127 }
Martyn Capewell72765d12020-03-23 14:25:53 +000012128 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12129 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12130 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12131 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12132 SVEStructuredLoadHelper(vform,
12133 pg,
12134 instr->GetRt(),
12135 addr,
12136 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012137}
12138
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012139void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
12140 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012141 SimVRegister& zt = ReadVRegister(instr->GetRt());
12142 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12143
12144 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12145 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
12146
12147 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012148 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
12149 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012150 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012151 break;
12152 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012153 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012154 break;
12155 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012156 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012157 break;
12158 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012159 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012160 break;
12161 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012162 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012163 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012164 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012165 ld1(kFormat16B, zt, addr + offset);
12166 mov_zeroing(vform, zt, pg, zt);
12167 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012168}
12169
12170void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
12171 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012172 SimVRegister& zt = ReadVRegister(instr->GetRt());
12173 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12174
12175 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12176 uint64_t offset = ReadXRegister(instr->GetRm());
12177
12178 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012179 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
12180 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012181 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012182 break;
12183 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012184 vform = kFormatVnD;
12185 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012186 break;
12187 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012188 vform = kFormatVnH;
12189 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012190 break;
12191 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012192 vform = kFormatVnS;
12193 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012194 break;
12195 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012196 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012197 break;
12198 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000012199 ld1(kFormat16B, zt, addr + offset);
12200 mov_zeroing(vform, zt, pg, zt);
12201 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012202}
12203
12204void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12205 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012206 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12207 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012208 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012209 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012210 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012211 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012212 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012213 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012214 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012215 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012216 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012217 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012218 case LD4W_z_p_bi_contiguous: {
12219 int vl = GetVectorLengthInBytes();
12220 int msz = instr->ExtractBits(24, 23);
12221 int reg_count = instr->ExtractBits(22, 21) + 1;
12222 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12223 LogicSVEAddressVector addr(
12224 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12225 addr.SetMsizeInBytesLog2(msz);
12226 addr.SetRegCount(reg_count);
12227 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12228 ReadPRegister(instr->GetPgLow8()),
12229 instr->GetRt(),
12230 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012231 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000012232 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012233 default:
12234 VIXL_UNIMPLEMENTED();
12235 break;
12236 }
12237}
12238
12239void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12240 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012241 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12242 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012243 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012244 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012245 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012246 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012247 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012248 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012249 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012250 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012251 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012252 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000012253 case LD4W_z_p_br_contiguous: {
12254 int msz = instr->ExtractBits(24, 23);
12255 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12256 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12257 LogicSVEAddressVector addr(
12258 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12259 addr.SetMsizeInBytesLog2(msz);
12260 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12261 SVEStructuredLoadHelper(vform,
12262 ReadPRegister(instr->GetPgLow8()),
12263 instr->GetRt(),
12264 addr,
12265 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012266 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000012267 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012268 default:
12269 VIXL_UNIMPLEMENTED();
12270 break;
12271 }
12272}
12273
12274void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12275 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012276 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12277 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012278 case ST1W_z_p_bz_s_x32_scaled: {
12279 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12280 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12281 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12282 uint64_t base = ReadXRegister(instr->GetRn());
12283 SVEOffsetModifier mod =
12284 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12285 LogicSVEAddressVector addr(base,
12286 &ReadVRegister(instr->GetRm()),
12287 kFormatVnS,
12288 mod,
12289 scale);
12290 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12291 SVEStructuredStoreHelper(kFormatVnS,
12292 ReadPRegister(instr->GetPgLow8()),
12293 instr->GetRt(),
12294 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012295 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012296 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012297 default:
12298 VIXL_UNIMPLEMENTED();
12299 break;
12300 }
12301}
12302
12303void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12304 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012305 switch (
12306 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12307 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012308 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012309 case ST1W_z_p_bz_s_x32_unscaled: {
12310 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12311 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12312 uint64_t base = ReadXRegister(instr->GetRn());
12313 SVEOffsetModifier mod =
12314 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12315 LogicSVEAddressVector addr(base,
12316 &ReadVRegister(instr->GetRm()),
12317 kFormatVnS,
12318 mod);
12319 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12320 SVEStructuredStoreHelper(kFormatVnS,
12321 ReadPRegister(instr->GetPgLow8()),
12322 instr->GetRt(),
12323 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012324 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012325 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012326 default:
12327 VIXL_UNIMPLEMENTED();
12328 break;
12329 }
12330}
12331
12332void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12333 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012334 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012335 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12336 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012337 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012338 break;
12339 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012340 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012341 break;
12342 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012343 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012344 break;
12345 default:
12346 VIXL_UNIMPLEMENTED();
12347 break;
12348 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012349 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12350 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12351 addr.SetMsizeInBytesLog2(msz);
12352 SVEStructuredStoreHelper(kFormatVnS,
12353 ReadPRegister(instr->GetPgLow8()),
12354 instr->GetRt(),
12355 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012356}
12357
12358void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12359 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012360 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12361 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012362 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012363 case ST1W_z_p_bz_d_64_scaled: {
12364 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12365 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12366 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12367 uint64_t base = ReadXRegister(instr->GetRn());
12368 LogicSVEAddressVector addr(base,
12369 &ReadVRegister(instr->GetRm()),
12370 kFormatVnD,
12371 SVE_LSL,
12372 scale);
12373 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12374 SVEStructuredStoreHelper(kFormatVnD,
12375 ReadPRegister(instr->GetPgLow8()),
12376 instr->GetRt(),
12377 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012378 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012379 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012380 default:
12381 VIXL_UNIMPLEMENTED();
12382 break;
12383 }
12384}
12385
12386void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12387 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012388 switch (
12389 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12390 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012391 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012392 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012393 case ST1W_z_p_bz_d_64_unscaled: {
12394 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12395 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012396 uint64_t base = ReadXRegister(instr->GetRn());
12397 LogicSVEAddressVector addr(base,
12398 &ReadVRegister(instr->GetRm()),
12399 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070012400 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012401 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12402 SVEStructuredStoreHelper(kFormatVnD,
12403 ReadPRegister(instr->GetPgLow8()),
12404 instr->GetRt(),
12405 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012406 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010012407 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012408 default:
12409 VIXL_UNIMPLEMENTED();
12410 break;
12411 }
12412}
12413
12414void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12415 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012416 switch (instr->Mask(
12417 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12418 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012419 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012420 case ST1W_z_p_bz_d_x32_scaled: {
12421 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12422 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12423 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12424 uint64_t base = ReadXRegister(instr->GetRn());
12425 SVEOffsetModifier mod =
12426 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12427 LogicSVEAddressVector addr(base,
12428 &ReadVRegister(instr->GetRm()),
12429 kFormatVnD,
12430 mod,
12431 scale);
12432 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12433 SVEStructuredStoreHelper(kFormatVnD,
12434 ReadPRegister(instr->GetPgLow8()),
12435 instr->GetRt(),
12436 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012437 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012438 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012439 default:
12440 VIXL_UNIMPLEMENTED();
12441 break;
12442 }
12443}
12444
12445void Simulator::
12446 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12447 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012448 switch (instr->Mask(
12449 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12450 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012451 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012452 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070012453 case ST1W_z_p_bz_d_x32_unscaled: {
12454 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12455 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12456 uint64_t base = ReadXRegister(instr->GetRn());
12457 SVEOffsetModifier mod =
12458 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12459 LogicSVEAddressVector addr(base,
12460 &ReadVRegister(instr->GetRm()),
12461 kFormatVnD,
12462 mod);
12463 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12464 SVEStructuredStoreHelper(kFormatVnD,
12465 ReadPRegister(instr->GetPgLow8()),
12466 instr->GetRt(),
12467 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012468 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070012469 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012470 default:
12471 VIXL_UNIMPLEMENTED();
12472 break;
12473 }
12474}
12475
12476void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12477 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010012478 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012479 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12480 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012481 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012482 break;
12483 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012484 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012485 break;
12486 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012487 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012488 break;
12489 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010012490 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012491 break;
12492 default:
12493 VIXL_UNIMPLEMENTED();
12494 break;
12495 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010012496 uint64_t imm = instr->ExtractBits(20, 16) << msz;
12497 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12498 addr.SetMsizeInBytesLog2(msz);
12499 SVEStructuredStoreHelper(kFormatVnD,
12500 ReadPRegister(instr->GetPgLow8()),
12501 instr->GetRt(),
12502 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012503}
12504
12505void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12506 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012507 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12508 VectorFormat vform = kFormatUndefined;
12509
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012510 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12511 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012512 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012513 break;
12514 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012515 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012516 break;
12517 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012518 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012519 break;
12520 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012521 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012522 break;
12523 default:
12524 VIXL_UNIMPLEMENTED();
12525 break;
12526 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012527 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12528 int vl = GetVectorLengthInBytes();
12529 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12530 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12531 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12532 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012533}
12534
12535void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12536 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012537 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12538 VectorFormat vform = kFormatUndefined;
12539
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012540 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12541 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012542 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012543 break;
12544 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012545 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012546 break;
12547 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012548 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012549 break;
12550 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012551 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012552 break;
12553 default:
12554 VIXL_UNIMPLEMENTED();
12555 break;
12556 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000012557 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12558 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12559 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12560 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12561 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012562}
12563
12564void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12565 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012566 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12567 case ST1B_z_p_bi:
12568 case ST1D_z_p_bi:
12569 case ST1H_z_p_bi:
12570 case ST1W_z_p_bi: {
12571 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012572 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12573 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12574 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12575 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12576 uint64_t offset =
12577 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012578 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010012579 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012580 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012581 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12582 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012583 ReadPRegister(instr->GetPgLow8()),
12584 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012585 addr);
12586 break;
12587 }
12588 default:
12589 VIXL_UNIMPLEMENTED();
12590 break;
12591 }
12592}
12593
12594void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12595 const Instruction* instr) {
12596 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12597 case ST1B_z_p_br:
12598 case ST1D_z_p_br:
12599 case ST1H_z_p_br:
12600 case ST1W_z_p_br: {
12601 uint64_t offset = ReadXRegister(instr->GetRm());
12602 offset <<= instr->ExtractBits(24, 23);
12603 VectorFormat vform =
12604 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12605 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012606 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12607 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012608 ReadPRegister(instr->GetPgLow8()),
12609 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012610 addr);
12611 break;
12612 }
12613 default:
12614 VIXL_UNIMPLEMENTED();
12615 break;
12616 }
12617}
12618
12619void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12620 const Instruction* instr) {
12621 VectorFormat vform = instr->GetSVEVectorFormat();
12622 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12623 SimVRegister z_result;
12624
12625 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12626 case CPY_z_p_v:
12627 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12628 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12629 break;
12630 default:
12631 VIXL_UNIMPLEMENTED();
12632 break;
12633 }
12634}
12635
12636void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12637 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012638 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12639 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012640 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012641 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012642 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012643 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012644 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012645 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012646 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012647 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012648 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012649 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012650 case ST4W_z_p_bi_contiguous: {
12651 int vl = GetVectorLengthInBytes();
12652 int msz = instr->ExtractBits(24, 23);
12653 int reg_count = instr->ExtractBits(22, 21) + 1;
12654 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12655 LogicSVEAddressVector addr(
12656 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12657 addr.SetMsizeInBytesLog2(msz);
12658 addr.SetRegCount(reg_count);
12659 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12660 ReadPRegister(instr->GetPgLow8()),
12661 instr->GetRt(),
12662 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012663 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000012664 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012665 default:
12666 VIXL_UNIMPLEMENTED();
12667 break;
12668 }
12669}
12670
12671void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12672 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012673 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12674 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012675 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012676 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012677 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012678 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012679 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012680 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012681 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012682 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012683 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012684 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012685 case ST4W_z_p_br_contiguous: {
12686 int msz = instr->ExtractBits(24, 23);
12687 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12688 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12689 LogicSVEAddressVector addr(
12690 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12691 addr.SetMsizeInBytesLog2(msz);
12692 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12693 SVEStructuredStoreHelper(vform,
12694 ReadPRegister(instr->GetPgLow8()),
12695 instr->GetRt(),
12696 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012697 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000012698 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012699 default:
12700 VIXL_UNIMPLEMENTED();
12701 break;
12702 }
12703}
12704
12705void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12706 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12707 case STR_p_bi: {
12708 SimPRegister& pt = ReadPRegister(instr->GetPt());
12709 int pl = GetPredicateLengthInBytes();
12710 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12711 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12712 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12713 for (int i = 0; i < pl; i++) {
12714 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
12715 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012716 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012717 break;
12718 }
12719 default:
12720 VIXL_UNIMPLEMENTED();
12721 break;
12722 }
12723}
12724
12725void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12726 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12727 case STR_z_bi: {
12728 SimVRegister& zt = ReadVRegister(instr->GetRt());
12729 int vl = GetVectorLengthInBytes();
12730 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12731 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12732 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12733 for (int i = 0; i < vl; i++) {
12734 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
12735 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000012736 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012737 break;
12738 }
12739 default:
12740 VIXL_UNIMPLEMENTED();
12741 break;
12742 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012743}
12744
12745void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012746 VectorFormat vform = instr->GetSVEVectorFormat();
12747 SimVRegister& zda = ReadVRegister(instr->GetRd());
12748 SimVRegister& zn = ReadVRegister(instr->GetRn());
12749
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012750 switch (instr->Mask(SVEMulIndexMask)) {
12751 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012752 sdot(vform,
12753 zda,
12754 zn,
12755 ReadVRegister(instr->ExtractBits(19, 16)),
12756 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012757 break;
12758 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012759 sdot(vform,
12760 zda,
12761 zn,
12762 ReadVRegister(instr->ExtractBits(18, 16)),
12763 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012764 break;
12765 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012766 udot(vform,
12767 zda,
12768 zn,
12769 ReadVRegister(instr->ExtractBits(19, 16)),
12770 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012771 break;
12772 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070012773 udot(vform,
12774 zda,
12775 zn,
12776 ReadVRegister(instr->ExtractBits(18, 16)),
12777 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012778 break;
12779 default:
12780 VIXL_UNIMPLEMENTED();
12781 break;
12782 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012783}
12784
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012785void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012786 SimPRegister& pd = ReadPRegister(instr->GetPd());
12787 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12788 SimPRegister& pn = ReadPRegister(instr->GetPn());
12789 SimPRegister result;
12790
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012791 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012792 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012793 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012794 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012795 break;
12796 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012797 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080012798 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012799 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012800 default:
12801 VIXL_UNIMPLEMENTED();
12802 break;
12803 }
TatWai Chong5d872292020-01-02 15:39:51 -080012804
12805 if (instr->ExtractBit(4) == 1) {
12806 mov_merging(pd, pg, result);
12807 } else {
12808 mov_zeroing(pd, pg, result);
12809 }
12810
12811 // Set flag if needed.
12812 if (instr->ExtractBit(22) == 1) {
12813 PredTest(kFormatVnB, pg, pd);
12814 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012815}
12816
12817void Simulator::VisitSVEPropagateBreakToNextPartition(
12818 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080012819 SimPRegister& pdm = ReadPRegister(instr->GetPd());
12820 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12821 SimPRegister& pn = ReadPRegister(instr->GetPn());
12822
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012823 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012824 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012825 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080012826 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012827 break;
12828 default:
12829 VIXL_UNIMPLEMENTED();
12830 break;
12831 }
TatWai Chong5d872292020-01-02 15:39:51 -080012832
12833 // Set flag if needed.
12834 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010012835 // Note that this ignores `pg`.
12836 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080012837 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012838}
12839
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012840void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012841 SimPRegister& pd = ReadPRegister(instr->GetPd());
12842 SimPRegister& pn = ReadPRegister(instr->GetPn());
12843
12844 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12845 SimVRegister zero;
12846 dup_immediate(kFormatVnB, zero, 0);
12847
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012848 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012849 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012850 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012851 break;
12852 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012853 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012854 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012855 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012856 VIXL_UNIMPLEMENTED();
12857 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012858 }
TatWai Chong47c26842020-02-10 01:51:32 -080012859 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012860}
12861
12862void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012863 VectorFormat vform = instr->GetSVEVectorFormat();
12864 SimPRegister& pd = ReadPRegister(instr->GetPd());
12865 SimPRegister& pn = ReadPRegister(instr->GetPn());
12866 SimPRegister& pm = ReadPRegister(instr->GetPm());
12867
12868 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12869 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12870
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012871 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012872 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012873 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012874 break;
12875 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012876 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012877 break;
12878 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012879 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012880 break;
12881 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012882 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012883 break;
12884 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012885 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012886 break;
12887 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012888 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012889 break;
12890 default:
12891 VIXL_UNIMPLEMENTED();
12892 break;
12893 }
TatWai Chong47c26842020-02-10 01:51:32 -080012894 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012895}
12896
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012897void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012898 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012899 case REV_p_p: {
12900 VectorFormat vform = instr->GetSVEVectorFormat();
12901 SimPRegister& pn = ReadPRegister(instr->GetPn());
12902 SimPRegister& pd = ReadPRegister(instr->GetPd());
12903 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12904 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080012905 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012906 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000012907 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012908 default:
12909 VIXL_UNIMPLEMENTED();
12910 break;
12911 }
12912}
12913
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012914void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000012915 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12916 // Second source register "Zm" is encoded where "Zn" would usually be.
12917 SimVRegister& zm = ReadVRegister(instr->GetRn());
12918
12919 const int imm8h_mask = 0x001F0000;
12920 const int imm8l_mask = 0x00001C00;
12921 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
12922 int vl = GetVectorLengthInBytes();
12923 index = (index >= vl) ? 0 : index;
12924
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012925 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
12926 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000012927 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012928 break;
12929 default:
12930 VIXL_UNIMPLEMENTED();
12931 break;
12932 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012933}
12934
12935void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000012936 VectorFormat vform = instr->GetSVEVectorFormat();
12937 SimVRegister& zd = ReadVRegister(instr->GetRd());
12938 SimVRegister& zn = ReadVRegister(instr->GetRn());
12939 SimVRegister& zm = ReadVRegister(instr->GetRm());
12940
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012941 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
12942 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012943 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012944 break;
12945 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012946 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012947 break;
12948 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012949 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012950 break;
12951 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012952 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012953 break;
12954 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012955 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012956 break;
12957 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000012958 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012959 break;
12960 default:
12961 VIXL_UNIMPLEMENTED();
12962 break;
12963 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000012964}
12965
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012966void Simulator::VisitSVEConditionallyBroadcastElementToVector(
12967 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000012968 VectorFormat vform = instr->GetSVEVectorFormat();
12969 SimVRegister& zdn = ReadVRegister(instr->GetRd());
12970 SimVRegister& zm = ReadVRegister(instr->GetRn());
12971 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12972
12973 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012974 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012975 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012976 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012977 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012978 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000012979 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000012980 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012981 default:
12982 VIXL_UNIMPLEMENTED();
12983 break;
12984 }
Martyn Capewellf804b602020-02-24 18:57:18 +000012985
12986 if (active_offset >= 0) {
12987 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
12988 if (value.first) {
12989 dup_immediate(vform, zdn, value.second);
12990 } else {
12991 // Trigger a line of trace for the operation, even though it doesn't
12992 // change the register value.
12993 mov(vform, zdn, zdn);
12994 }
12995 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010012996}
12997
12998void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
12999 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013000 VectorFormat vform = instr->GetSVEVectorFormat();
13001 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13002 SimVRegister& zm = ReadVRegister(instr->GetRn());
13003 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13004
13005 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013006 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
13007 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013008 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013009 break;
13010 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013011 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013012 break;
13013 default:
13014 VIXL_UNIMPLEMENTED();
13015 break;
13016 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013017
13018 if (active_offset >= 0) {
13019 LogicVRegister dst(vdn);
13020 uint64_t src1_value = dst.Uint(vform, 0);
13021 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
13022 dup_immediate(vform, vdn, 0);
13023 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
13024 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013025}
13026
13027void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
13028 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013029 VectorFormat vform = instr->GetSVEVectorFormat();
13030 SimVRegister& zm = ReadVRegister(instr->GetRn());
13031 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13032
13033 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013034 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
13035 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013036 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013037 break;
13038 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013039 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013040 break;
13041 default:
13042 VIXL_UNIMPLEMENTED();
13043 break;
13044 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013045
13046 if (active_offset >= 0) {
13047 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13048 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13049 GetUintMask(LaneSizeInBitsFromFormat(vform));
13050 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13051 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013052}
13053
13054void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13055 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013056 VectorFormat vform = instr->GetSVEVectorFormat();
13057 SimVRegister& vdn = ReadVRegister(instr->GetRd());
13058 SimVRegister& zm = ReadVRegister(instr->GetRn());
13059 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13060
13061 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013062 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13063 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013064 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013065 break;
13066 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013067 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013068 break;
13069 default:
13070 VIXL_UNIMPLEMENTED();
13071 break;
13072 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013073
13074 if (active_offset >= 0) {
13075 LogicVRegister dst(vdn);
13076 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13077 dup_immediate(vform, vdn, 0);
13078 dst.SetUint(vform, 0, value.second);
13079 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013080}
13081
13082void Simulator::VisitSVEExtractElementToGeneralRegister(
13083 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013084 VectorFormat vform = instr->GetSVEVectorFormat();
13085 SimVRegister& zm = ReadVRegister(instr->GetRn());
13086 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13087
13088 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013089 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13090 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013091 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013092 break;
13093 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013094 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013095 break;
13096 default:
13097 VIXL_UNIMPLEMENTED();
13098 break;
13099 }
Martyn Capewellf804b602020-02-24 18:57:18 +000013100
13101 if (active_offset >= 0) {
13102 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13103 WriteXRegister(instr->GetRd(), value.second);
13104 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013105}
13106
13107void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013108 VectorFormat vform = instr->GetSVEVectorFormat();
13109 SimVRegister& zd = ReadVRegister(instr->GetRd());
13110 SimVRegister& zn = ReadVRegister(instr->GetRn());
13111 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13112
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013113 switch (instr->Mask(SVECompressActiveElementsMask)) {
13114 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000013115 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013116 break;
13117 default:
13118 VIXL_UNIMPLEMENTED();
13119 break;
13120 }
13121}
13122
13123void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13124 const Instruction* instr) {
13125 VectorFormat vform = instr->GetSVEVectorFormat();
13126 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13127 SimVRegister z_result;
13128
13129 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013130 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010013131 dup_immediate(vform,
13132 z_result,
13133 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13134 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013135 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013136 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013137 VIXL_UNIMPLEMENTED();
13138 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013139 }
13140}
13141
13142void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013143 VectorFormat vform = instr->GetSVEVectorFormat();
13144 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13145 SimVRegister& zd = ReadVRegister(instr->GetRd());
13146
13147 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013148 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013149 case CPY_z_p_i: {
13150 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
13151 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13152 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013153 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013154 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013155 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013156 VIXL_UNIMPLEMENTED();
13157 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013158 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010013159
13160 if (instr->ExtractBit(14) != 0) {
13161 mov_merging(vform, zd, pg, result);
13162 } else {
13163 mov_zeroing(vform, zd, pg, result);
13164 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013165}
13166
13167void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000013168 SimVRegister& zd = ReadVRegister(instr->GetRd());
13169 SimVRegister& zn = ReadVRegister(instr->GetRn());
13170 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13171 SimVRegister result;
13172
13173 // In NEON, the chunk size in which elements are REVersed is in the
13174 // instruction mnemonic, and the element size attached to the register.
13175 // SVE reverses the semantics; the mapping to logic functions below is to
13176 // account for this.
13177 VectorFormat chunk_form = instr->GetSVEVectorFormat();
13178 VectorFormat element_form = kFormatUndefined;
13179
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013180 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013181 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013182 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013183 break;
13184 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013185 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13186 (chunk_form == kFormatVnD));
13187 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013188 break;
13189 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013190 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13191 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013192 break;
13193 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000013194 VIXL_ASSERT(chunk_form == kFormatVnD);
13195 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013196 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013197 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013198 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013199 break;
13200 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000013201
13202 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13203 VIXL_ASSERT(element_form != kFormatUndefined);
13204 switch (chunk_form) {
13205 case kFormatVnH:
13206 rev16(element_form, result, zn);
13207 break;
13208 case kFormatVnS:
13209 rev32(element_form, result, zn);
13210 break;
13211 case kFormatVnD:
13212 rev64(element_form, result, zn);
13213 break;
13214 default:
13215 VIXL_UNIMPLEMENTED();
13216 }
13217 }
13218
13219 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013220}
13221
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013222void Simulator::VisitSVEVectorSplice(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000013223 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013224 SimVRegister& zd = ReadVRegister(instr->GetRd());
13225 SimVRegister& zn = ReadVRegister(instr->GetRn());
13226 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
Martyn Capewellf804b602020-02-24 18:57:18 +000013227 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13228
Martyn Capewell1c7b9ae2020-11-03 14:40:16 +000013229 switch (form_hash_) {
13230 case Hash("splice_z_p_zz_des"):
13231 splice(vform, zd, pg, zd, zn);
13232 break;
13233 case Hash("splice_z_p_zz_con"):
13234 splice(vform, zd, pg, zn, zn2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013235 break;
13236 default:
13237 VIXL_UNIMPLEMENTED();
13238 break;
13239 }
13240}
TatWai Chong4f28df72019-08-14 17:50:30 -070013241
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013242void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13243 SimVRegister& zd = ReadVRegister(instr->GetRd());
13244 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13245 case DUP_z_r:
13246 dup_immediate(instr->GetSVEVectorFormat(),
13247 zd,
13248 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13249 break;
13250 default:
13251 VIXL_UNIMPLEMENTED();
13252 break;
13253 }
13254}
13255
13256void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13257 SimVRegister& zd = ReadVRegister(instr->GetRd());
13258 VectorFormat vform = instr->GetSVEVectorFormat();
13259 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13260 case INSR_z_v:
13261 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13262 break;
13263 default:
13264 VIXL_UNIMPLEMENTED();
13265 break;
13266 }
13267}
13268
13269void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13270 SimVRegister& zd = ReadVRegister(instr->GetRd());
13271 VectorFormat vform = instr->GetSVEVectorFormat();
13272 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13273 case INSR_z_r:
13274 insr(vform, zd, ReadXRegister(instr->GetRn()));
13275 break;
13276 default:
13277 VIXL_UNIMPLEMENTED();
13278 break;
13279 }
13280}
13281
13282void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13283 SimVRegister& zd = ReadVRegister(instr->GetRd());
13284 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070013285 case DUP_z_zi: {
13286 std::pair<int, int> index_and_lane_size =
13287 instr->GetSVEPermuteIndexAndLaneSizeLog2();
13288 int index = index_and_lane_size.first;
13289 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13290 VectorFormat vform =
13291 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13292 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13293 // Out of bounds, set the destination register to zero.
13294 dup_immediate(kFormatVnD, zd, 0);
13295 } else {
13296 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13297 }
13298 return;
13299 }
TatWai Chong4f28df72019-08-14 17:50:30 -070013300 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013301 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070013302 break;
13303 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013304}
TatWai Chong4f28df72019-08-14 17:50:30 -070013305
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013306void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13307 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070013308 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013309 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013310 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013311 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013312 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013313 default:
13314 VIXL_UNIMPLEMENTED();
13315 break;
13316 }
13317}
13318
13319void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13320 SimVRegister& zd = ReadVRegister(instr->GetRd());
13321 VectorFormat vform = instr->GetSVEVectorFormat();
13322 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013323 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013324 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013325 break;
13326 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013327 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013328 break;
13329 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013330 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013331 break;
13332 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070013333 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13334 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013335 default:
13336 VIXL_UNIMPLEMENTED();
13337 break;
13338 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013339}
13340
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013341void Simulator::VisitSVETableLookup(const Instruction* instr) {
Martyn Capewell99c60492020-10-30 08:14:39 +000013342 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013343 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewell99c60492020-10-30 08:14:39 +000013344 SimVRegister& zn = ReadVRegister(instr->GetRn());
13345 SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13346 SimVRegister& zm = ReadVRegister(instr->GetRm());
13347
13348 switch (form_hash_) {
13349 case Hash("tbl_z_zz_1"):
13350 tbl(vform, zd, zn, zm);
13351 break;
13352 case Hash("tbl_z_zz_2"):
13353 tbl(vform, zd, zn, zn2, zm);
13354 break;
13355 case Hash("tbx_z_zz"):
13356 tbx(vform, zd, zn, zm);
13357 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013358 default:
Martyn Capewell99c60492020-10-30 08:14:39 +000013359 VIXL_UNIMPLEMENTED();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013360 break;
13361 }
13362}
13363
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013364void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013365 VectorFormat vform = instr->GetSVEVectorFormat();
13366 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13367 SimPRegister& pn = ReadPRegister(instr->GetPn());
13368
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013369 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013370 case CNTP_r_p_p: {
13371 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013372 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010013373 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013374 default:
13375 VIXL_UNIMPLEMENTED();
13376 break;
13377 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013378}
13379
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013380void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13381 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080013382 SimPRegister& pd = ReadPRegister(instr->GetPd());
13383 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13384 SimPRegister& pn = ReadPRegister(instr->GetPn());
13385 SimPRegister& pm = ReadPRegister(instr->GetPm());
13386 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070013387 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013388 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013389 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013390 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013391 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013392 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013393 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013394 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013395 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013396 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013397 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013398 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013399 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013400 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013401 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070013402 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080013403 result,
13404 pn,
13405 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013406 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080013407 case SEL_p_p_pp:
13408 sel(pd, pg, pn, pm);
13409 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013410 default:
13411 VIXL_UNIMPLEMENTED();
13412 break;
13413 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013414
13415 mov_zeroing(pd, pg, result);
13416 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13417 PredTest(kFormatVnB, pg, pd);
13418 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013419}
13420
Jacob Bramley0ce75842019-07-17 18:12:50 +010013421void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013422 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13423 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13424 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013425 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010013426 pfirst(pdn, pg, pdn);
13427 // TODO: Is this broken when pg == pdn?
13428 PredTest(kFormatVnB, pg, pdn);
13429 break;
13430 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013431 VIXL_UNIMPLEMENTED();
13432 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013433 }
13434}
13435
13436void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013437 // This group only contains PTRUE{S}, and there are no unallocated encodings.
13438 VIXL_STATIC_ASSERT(
13439 SVEPredicateInitializeMask ==
13440 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13441 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13442 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13443
13444 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13445 VectorFormat vform = instr->GetSVEVectorFormat();
13446
13447 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13448 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13449}
13450
13451void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013452 // This group only contains PNEXT, and there are no unallocated encodings.
13453 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13454 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13455
13456 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13457 LogicPRegister pdn = ReadPRegister(instr->GetPd());
13458 VectorFormat vform = instr->GetSVEVectorFormat();
13459
13460 pnext(vform, pdn, pg, pdn);
13461 // TODO: Is this broken when pg == pdn?
13462 PredTest(vform, pg, pdn);
13463}
13464
13465void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13466 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080013467 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13468 LogicPRegister pg(ReadPRegister(instr->GetPn()));
13469 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013470 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13471 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013472 // Do nothing.
13473 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013474 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080013475 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013476 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013477 default:
13478 VIXL_UNIMPLEMENTED();
13479 break;
13480 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080013481
13482 LogicPRegister ffr(ReadFFR());
13483 mov_zeroing(pd, pg, ffr);
13484
13485 if (flags == SetFlags) {
13486 PredTest(kFormatVnB, pg, pd);
13487 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010013488}
13489
13490void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13491 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013492 LogicPRegister pd(ReadPRegister(instr->GetPd()));
13493 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010013494 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013495 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080013496 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013497 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013498 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013499 VIXL_UNIMPLEMENTED();
13500 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010013501 }
13502}
13503
13504void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013505 switch (instr->Mask(SVEPredicateTestMask)) {
13506 case PTEST_p_p:
13507 PredTest(kFormatVnB,
13508 ReadPRegister(instr->ExtractBits(13, 10)),
13509 ReadPRegister(instr->GetPn()));
13510 break;
13511 default:
13512 VIXL_UNIMPLEMENTED();
13513 break;
13514 }
13515}
13516
13517void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010013518 switch (instr->Mask(SVEPredicateZeroMask)) {
13519 case PFALSE_p:
13520 pfalse(ReadPRegister(instr->GetPd()));
13521 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013522 default:
13523 VIXL_UNIMPLEMENTED();
13524 break;
13525 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013526}
13527
13528void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080013529 SimPRegister& pd = ReadPRegister(instr->GetPd());
13530 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13531 SimPRegister& pn = ReadPRegister(instr->GetPn());
13532 SimPRegister& pm = ReadPRegister(instr->GetPm());
13533
13534 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013535 switch (instr->Mask(SVEPropagateBreakMask)) {
13536 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013537 set_flags = true;
13538 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013539 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013540 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013541 break;
13542 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013543 set_flags = true;
13544 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013545 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080013546 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013547 break;
13548 default:
13549 VIXL_UNIMPLEMENTED();
13550 break;
13551 }
TatWai Chong38303d92019-12-02 15:49:29 -080013552
13553 if (set_flags) {
13554 PredTest(kFormatVnB, pg, pd);
13555 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013556}
13557
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013558void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13559 uint64_t length = 0;
13560 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13561 case ADDPL_r_ri:
13562 length = GetPredicateLengthInBytes();
13563 break;
13564 case ADDVL_r_ri:
13565 length = GetVectorLengthInBytes();
13566 break;
13567 default:
13568 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013569 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013570 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013571 WriteXRegister(instr->GetRd(),
13572 base + (length * instr->GetImmSVEVLScale()),
13573 LogRegWrites,
13574 Reg31IsStackPointer);
13575}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010013576
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013577void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13578 int64_t scale = instr->GetImmSVEVLScale();
13579
13580 switch (instr->Mask(SVEStackFrameSizeMask)) {
13581 case RDVL_r_i:
13582 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13583 break;
13584 default:
13585 VIXL_UNIMPLEMENTED();
13586 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013587}
13588
13589void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013590 // The only instruction in this group is `sel`, and there are no unused
13591 // encodings.
13592 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13593
13594 VectorFormat vform = instr->GetSVEVectorFormat();
13595 SimVRegister& zd = ReadVRegister(instr->GetRd());
13596 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13597 SimVRegister& zn = ReadVRegister(instr->GetRn());
13598 SimVRegister& zm = ReadVRegister(instr->GetRm());
13599
13600 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013601}
13602
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013603void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013604 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013605 case SETFFR_f: {
13606 LogicPRegister ffr(ReadFFR());
13607 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013608 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013609 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013610 default:
13611 VIXL_UNIMPLEMENTED();
13612 break;
13613 }
13614}
13615
13616void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010013617 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080013618 case WRFFR_f_p: {
13619 SimPRegister pn(ReadPRegister(instr->GetPn()));
13620 bool last_active = true;
13621 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13622 bool active = pn.GetBit(i);
13623 if (active && !last_active) {
13624 // `pn` is non-monotonic. This is UNPREDICTABLE.
13625 VIXL_ABORT();
13626 }
13627 last_active = active;
13628 }
13629 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013630 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080013631 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000013632 default:
13633 VIXL_UNIMPLEMENTED();
13634 break;
13635 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000013636}
Alexandre Ramesd3832962016-07-04 15:03:43 +010013637
TatWai Chong6205eb42019-09-24 10:07:20 +010013638void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010013639 bool is_signed;
13640 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13641 case LD1B_z_p_bi_u8:
13642 case LD1B_z_p_bi_u16:
13643 case LD1B_z_p_bi_u32:
13644 case LD1B_z_p_bi_u64:
13645 case LD1H_z_p_bi_u16:
13646 case LD1H_z_p_bi_u32:
13647 case LD1H_z_p_bi_u64:
13648 case LD1W_z_p_bi_u32:
13649 case LD1W_z_p_bi_u64:
13650 case LD1D_z_p_bi_u64:
13651 is_signed = false;
13652 break;
13653 case LD1SB_z_p_bi_s16:
13654 case LD1SB_z_p_bi_s32:
13655 case LD1SB_z_p_bi_s64:
13656 case LD1SH_z_p_bi_s32:
13657 case LD1SH_z_p_bi_s64:
13658 case LD1SW_z_p_bi_s64:
13659 is_signed = true;
13660 break;
13661 default:
13662 // This encoding group is complete, so no other values should be possible.
13663 VIXL_UNREACHABLE();
13664 is_signed = false;
13665 break;
13666 }
13667
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013668 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010013669 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13670 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010013671 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13672 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13673 uint64_t offset =
13674 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013675 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010013676 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013677 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13678 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013679 ReadPRegister(instr->GetPgLow8()),
13680 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013681 addr,
13682 is_signed);
13683}
13684
13685void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13686 const Instruction* instr) {
13687 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010013688 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13689 case LD1B_z_p_br_u8:
13690 case LD1B_z_p_br_u16:
13691 case LD1B_z_p_br_u32:
13692 case LD1B_z_p_br_u64:
13693 case LD1H_z_p_br_u16:
13694 case LD1H_z_p_br_u32:
13695 case LD1H_z_p_br_u64:
13696 case LD1W_z_p_br_u32:
13697 case LD1W_z_p_br_u64:
13698 case LD1D_z_p_br_u64:
13699 is_signed = false;
13700 break;
13701 case LD1SB_z_p_br_s16:
13702 case LD1SB_z_p_br_s32:
13703 case LD1SB_z_p_br_s64:
13704 case LD1SH_z_p_br_s32:
13705 case LD1SH_z_p_br_s64:
13706 case LD1SW_z_p_br_s64:
13707 is_signed = true;
13708 break;
13709 default:
13710 // This encoding group is complete, so no other values should be possible.
13711 VIXL_UNREACHABLE();
13712 is_signed = false;
13713 break;
13714 }
13715
13716 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13717 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13718 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13719 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13720 uint64_t offset = ReadXRegister(instr->GetRm());
13721 offset <<= msize_in_bytes_log2;
13722 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000013723 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13724 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010013725 ReadPRegister(instr->GetPgLow8()),
13726 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010013727 addr,
13728 is_signed);
13729}
13730
Alexandre Ramesd3832962016-07-04 15:03:43 +010013731void Simulator::DoUnreachable(const Instruction* instr) {
13732 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13733 (instr->GetImmException() == kUnreachableOpcode));
13734
13735 fprintf(stream_,
13736 "Hit UNREACHABLE marker at pc=%p.\n",
13737 reinterpret_cast<const void*>(instr));
13738 abort();
13739}
13740
13741
13742void Simulator::DoTrace(const Instruction* instr) {
13743 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13744 (instr->GetImmException() == kTraceOpcode));
13745
13746 // Read the arguments encoded inline in the instruction stream.
13747 uint32_t parameters;
13748 uint32_t command;
13749
13750 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13751 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13752 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13753
13754 switch (command) {
13755 case TRACE_ENABLE:
13756 SetTraceParameters(GetTraceParameters() | parameters);
13757 break;
13758 case TRACE_DISABLE:
13759 SetTraceParameters(GetTraceParameters() & ~parameters);
13760 break;
13761 default:
13762 VIXL_UNREACHABLE();
13763 }
13764
13765 WritePc(instr->GetInstructionAtOffset(kTraceLength));
13766}
13767
13768
13769void Simulator::DoLog(const Instruction* instr) {
13770 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13771 (instr->GetImmException() == kLogOpcode));
13772
13773 // Read the arguments encoded inline in the instruction stream.
13774 uint32_t parameters;
13775
13776 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13777 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13778
13779 // We don't support a one-shot LOG_DISASM.
13780 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13781 // Print the requested information.
13782 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13783 if (parameters & LOG_REGS) PrintRegisters();
13784 if (parameters & LOG_VREGS) PrintVRegisters();
13785
13786 WritePc(instr->GetInstructionAtOffset(kLogLength));
13787}
13788
13789
13790void Simulator::DoPrintf(const Instruction* instr) {
13791 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13792 (instr->GetImmException() == kPrintfOpcode));
13793
13794 // Read the arguments encoded inline in the instruction stream.
13795 uint32_t arg_count;
13796 uint32_t arg_pattern_list;
13797 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13798 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13799 memcpy(&arg_pattern_list,
13800 instr + kPrintfArgPatternListOffset,
13801 sizeof(arg_pattern_list));
13802
13803 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13804 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13805
13806 // We need to call the host printf function with a set of arguments defined by
13807 // arg_pattern_list. Because we don't know the types and sizes of the
13808 // arguments, this is very difficult to do in a robust and portable way. To
13809 // work around the problem, we pick apart the format string, and print one
13810 // format placeholder at a time.
13811
13812 // Allocate space for the format string. We take a copy, so we can modify it.
13813 // Leave enough space for one extra character per expected argument (plus the
13814 // '\0' termination).
13815 const char* format_base = ReadRegister<const char*>(0);
13816 VIXL_ASSERT(format_base != NULL);
13817 size_t length = strlen(format_base) + 1;
13818 char* const format = new char[length + arg_count];
13819
13820 // A list of chunks, each with exactly one format placeholder.
13821 const char* chunks[kPrintfMaxArgCount];
13822
13823 // Copy the format string and search for format placeholders.
13824 uint32_t placeholder_count = 0;
13825 char* format_scratch = format;
13826 for (size_t i = 0; i < length; i++) {
13827 if (format_base[i] != '%') {
13828 *format_scratch++ = format_base[i];
13829 } else {
13830 if (format_base[i + 1] == '%') {
13831 // Ignore explicit "%%" sequences.
13832 *format_scratch++ = format_base[i];
13833 i++;
13834 // Chunks after the first are passed as format strings to printf, so we
13835 // need to escape '%' characters in those chunks.
13836 if (placeholder_count > 0) *format_scratch++ = format_base[i];
13837 } else {
13838 VIXL_CHECK(placeholder_count < arg_count);
13839 // Insert '\0' before placeholders, and store their locations.
13840 *format_scratch++ = '\0';
13841 chunks[placeholder_count++] = format_scratch;
13842 *format_scratch++ = format_base[i];
13843 }
13844 }
13845 }
13846 VIXL_CHECK(placeholder_count == arg_count);
13847
13848 // Finally, call printf with each chunk, passing the appropriate register
13849 // argument. Normally, printf returns the number of bytes transmitted, so we
13850 // can emulate a single printf call by adding the result from each chunk. If
13851 // any call returns a negative (error) value, though, just return that value.
13852
13853 printf("%s", clr_printf);
13854
13855 // Because '\0' is inserted before each placeholder, the first string in
13856 // 'format' contains no format placeholders and should be printed literally.
13857 int result = printf("%s", format);
13858 int pcs_r = 1; // Start at x1. x0 holds the format string.
13859 int pcs_f = 0; // Start at d0.
13860 if (result >= 0) {
13861 for (uint32_t i = 0; i < placeholder_count; i++) {
13862 int part_result = -1;
13863
13864 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13865 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13866 switch (arg_pattern) {
13867 case kPrintfArgW:
13868 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13869 break;
13870 case kPrintfArgX:
13871 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13872 break;
13873 case kPrintfArgD:
13874 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13875 break;
13876 default:
13877 VIXL_UNREACHABLE();
13878 }
13879
13880 if (part_result < 0) {
13881 // Handle error values.
13882 result = part_result;
13883 break;
13884 }
13885
13886 result += part_result;
13887 }
13888 }
13889
13890 printf("%s", clr_normal);
13891
13892 // Printf returns its result in x0 (just like the C library's printf).
13893 WriteXRegister(0, result);
13894
13895 // The printf parameters are inlined in the code, so skip them.
13896 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13897
13898 // Set LR as if we'd just called a native printf function.
13899 WriteLr(ReadPc());
13900
13901 delete[] format;
13902}
13903
Alexandre Rames064e02d2016-07-12 11:53:13 +010013904
Alexandre Ramesca73ba02016-07-28 09:16:03 +010013905#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010013906void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013907 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013908 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13909 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013910 uintptr_t call_wrapper_address =
13911 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13912 uintptr_t function_address =
13913 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080013914 RuntimeCallType call_type = static_cast<RuntimeCallType>(
13915 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013916 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010013917 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013918
13919 if (call_type == kCallRuntime) {
13920 WriteRegister(kLinkRegCode,
13921 instr->GetInstructionAtOffset(kRuntimeCallLength));
13922 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010013923 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080013924 // Read the return address from `lr` and write it into `pc`.
13925 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010013926}
13927#else
13928void Simulator::DoRuntimeCall(const Instruction* instr) {
13929 USE(instr);
13930 VIXL_UNREACHABLE();
13931}
13932#endif
13933
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013934
13935void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
13936 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
13937
13938 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013939 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013940 std::numeric_limits<ElementType>::max());
13941
13942 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
13943
13944 size_t element_size = sizeof(ElementType);
13945 size_t offset = kConfigureCPUFeaturesListOffset;
13946
13947 // Read the kNone-terminated list of features.
13948 CPUFeatures parameters;
13949 while (true) {
13950 ElementType feature = Memory::Read<ElementType>(instr + offset);
13951 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010013952 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010013953 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
13954 }
13955
13956 switch (instr->GetImmException()) {
13957 case kSetCPUFeaturesOpcode:
13958 SetCPUFeatures(parameters);
13959 break;
13960 case kEnableCPUFeaturesOpcode:
13961 GetCPUFeatures()->Combine(parameters);
13962 break;
13963 case kDisableCPUFeaturesOpcode:
13964 GetCPUFeatures()->Remove(parameters);
13965 break;
13966 default:
13967 VIXL_UNREACHABLE();
13968 break;
13969 }
13970
13971 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
13972}
13973
13974
13975void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
13976 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13977 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
13978 USE(instr);
13979
13980 saved_cpu_features_.push_back(*GetCPUFeatures());
13981}
13982
13983
13984void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
13985 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13986 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
13987 USE(instr);
13988
13989 SetCPUFeatures(saved_cpu_features_.back());
13990 saved_cpu_features_.pop_back();
13991}
13992
13993
Alexandre Ramesd3832962016-07-04 15:03:43 +010013994} // namespace aarch64
13995} // namespace vixl
13996
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010013997#endif // VIXL_INCLUDE_SIMULATOR_AARCH64