Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/vixl/src/aarch64/assembler-sve-aarch64.cc
4261 views
1
// Copyright 2019, 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
27
#include "assembler-aarch64.h"
28
29
namespace vixl {
30
namespace aarch64 {
31
32
void Assembler::ResolveSVEImm8Shift(int* imm8, int* shift) {
33
if (*shift < 0) {
34
VIXL_ASSERT(*shift == -1);
35
// Derive the shift amount from the immediate.
36
if (IsInt8(*imm8)) {
37
*shift = 0;
38
} else if ((*imm8 % 256) == 0) {
39
*imm8 /= 256;
40
*shift = 8;
41
}
42
}
43
44
VIXL_ASSERT(IsInt8(*imm8));
45
VIXL_ASSERT((*shift == 0) || (*shift == 8));
46
}
47
48
// SVEAddressGeneration.
49
50
void Assembler::adr(const ZRegister& zd, const SVEMemOperand& addr) {
51
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
52
VIXL_ASSERT(addr.IsVectorPlusVector());
53
VIXL_ASSERT(
54
AreSameLaneSize(zd, addr.GetVectorBase(), addr.GetVectorOffset()));
55
56
int lane_size = zd.GetLaneSizeInBits();
57
VIXL_ASSERT((lane_size == kSRegSize) || (lane_size == kDRegSize));
58
59
int shift_amount = addr.GetShiftAmount();
60
VIXL_ASSERT((shift_amount >= 0) && (shift_amount <= 3));
61
62
Instr op = 0xffffffff;
63
Instr msz = shift_amount << 10;
64
SVEOffsetModifier mod = addr.GetOffsetModifier();
65
switch (mod) {
66
case SVE_UXTW:
67
VIXL_ASSERT(lane_size == kDRegSize);
68
op = ADR_z_az_d_u32_scaled;
69
break;
70
case SVE_SXTW:
71
VIXL_ASSERT(lane_size == kDRegSize);
72
op = ADR_z_az_d_s32_scaled;
73
break;
74
case SVE_LSL:
75
case NO_SVE_OFFSET_MODIFIER:
76
op = (lane_size == kSRegSize) ? ADR_z_az_s_same_scaled
77
: ADR_z_az_d_same_scaled;
78
break;
79
default:
80
VIXL_UNIMPLEMENTED();
81
}
82
Emit(op | msz | Rd(zd) | Rn(addr.GetVectorBase()) |
83
Rm(addr.GetVectorOffset()));
84
}
85
86
void Assembler::SVELogicalImmediate(const ZRegister& zdn,
87
uint64_t imm,
88
Instr op) {
89
unsigned bit_n, imm_s, imm_r;
90
unsigned lane_size = zdn.GetLaneSizeInBits();
91
// Check that the immediate can be encoded in the instruction.
92
if (IsImmLogical(imm, lane_size, &bit_n, &imm_s, &imm_r)) {
93
Emit(op | Rd(zdn) | SVEBitN(bit_n) | SVEImmRotate(imm_r, lane_size) |
94
SVEImmSetBits(imm_s, lane_size));
95
} else {
96
VIXL_UNREACHABLE();
97
}
98
}
99
100
void Assembler::and_(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
101
USE(zn);
102
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
103
VIXL_ASSERT(zd.Is(zn));
104
SVELogicalImmediate(zd, imm, AND_z_zi);
105
}
106
107
void Assembler::dupm(const ZRegister& zd, uint64_t imm) {
108
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
109
// DUPM_z_i is an SVEBroadcastBitmaskImmOp, but its encoding and constraints
110
// are similar enough to SVEBitwiseLogicalWithImm_UnpredicatedOp, that we can
111
// use the logical immediate encoder to get the correct behaviour.
112
SVELogicalImmediate(zd, imm, DUPM_z_i);
113
}
114
115
void Assembler::eor(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
116
USE(zn);
117
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
118
VIXL_ASSERT(zd.Is(zn));
119
SVELogicalImmediate(zd, imm, EOR_z_zi);
120
}
121
122
void Assembler::orr(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
123
USE(zn);
124
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
125
VIXL_ASSERT(zd.Is(zn));
126
SVELogicalImmediate(zd, imm, ORR_z_zi);
127
}
128
129
// SVEBitwiseLogicalUnpredicated.
130
void Assembler::and_(const ZRegister& zd,
131
const ZRegister& zn,
132
const ZRegister& zm) {
133
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
134
VIXL_ASSERT(zd.IsLaneSizeD());
135
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
136
Emit(AND_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
137
}
138
139
void Assembler::bic(const ZRegister& zd,
140
const ZRegister& zn,
141
const ZRegister& zm) {
142
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
143
VIXL_ASSERT(zd.IsLaneSizeD());
144
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
145
Emit(BIC_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
146
}
147
148
void Assembler::eor(const ZRegister& zd,
149
const ZRegister& zn,
150
const ZRegister& zm) {
151
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
152
VIXL_ASSERT(zd.IsLaneSizeD());
153
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
154
Emit(EOR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
155
}
156
157
void Assembler::orr(const ZRegister& zd,
158
const ZRegister& zn,
159
const ZRegister& zm) {
160
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
161
VIXL_ASSERT(zd.IsLaneSizeD());
162
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
163
Emit(ORR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));
164
}
165
166
// SVEBitwiseShiftPredicated.
167
168
void Assembler::SVEBitwiseShiftImmediatePred(const ZRegister& zdn,
169
const PRegisterM& pg,
170
Instr encoded_imm_and_tsz,
171
Instr op) {
172
Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)
173
<< 5;
174
Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;
175
Emit(op | tszh | tszl_and_imm | PgLow8(pg) | Rd(zdn));
176
}
177
178
void Assembler::asr(const ZRegister& zd,
179
const PRegisterM& pg,
180
const ZRegister& zn,
181
int shift) {
182
// ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
183
// 0000 0100 ..00 0000 100. .... .... ....
184
// tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 0 | Pg<12:10> |
185
// tszl<9:8> | imm3<7:5> | Zdn<4:0>
186
187
USE(zn);
188
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
189
VIXL_ASSERT(zd.Is(zn));
190
Instr encoded_imm =
191
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
192
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASR_z_p_zi);
193
}
194
195
void Assembler::asr(const ZRegister& zd,
196
const PRegisterM& pg,
197
const ZRegister& zn,
198
const ZRegister& zm) {
199
// ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
200
// 0000 0100 ..01 1000 100. .... .... ....
201
// size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |
202
// Zdn<4:0>
203
204
USE(zn);
205
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
206
VIXL_ASSERT(zd.Is(zn));
207
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
208
((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
209
(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
210
Instr op = ASR_z_p_zw;
211
if (AreSameLaneSize(zd, zn, zm)) {
212
op = ASR_z_p_zz;
213
}
214
Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
215
}
216
217
void Assembler::asrd(const ZRegister& zd,
218
const PRegisterM& pg,
219
const ZRegister& zn,
220
int shift) {
221
// ASRD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
222
// 0000 0100 ..00 0100 100. .... .... ....
223
// tszh<23:22> | opc<19:18> = 01 | L<17> = 0 | U<16> = 0 | Pg<12:10> |
224
// tszl<9:8> | imm3<7:5> | Zdn<4:0>
225
226
USE(zn);
227
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
228
VIXL_ASSERT(zd.Is(zn));
229
230
Instr encoded_imm =
231
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
232
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASRD_z_p_zi);
233
}
234
235
void Assembler::asrr(const ZRegister& zd,
236
const PRegisterM& pg,
237
const ZRegister& zn,
238
const ZRegister& zm) {
239
// ASRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
240
// 0000 0100 ..01 0100 100. .... .... ....
241
// size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |
242
// Zdn<4:0>
243
244
USE(zn);
245
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
246
VIXL_ASSERT(zd.Is(zn));
247
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
248
249
Emit(ASRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
250
}
251
252
void Assembler::lsl(const ZRegister& zd,
253
const PRegisterM& pg,
254
const ZRegister& zn,
255
int shift) {
256
// LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
257
// 0000 0100 ..00 0011 100. .... .... ....
258
// tszh<23:22> | opc<19:18> = 00 | L<17> = 1 | U<16> = 1 | Pg<12:10> |
259
// tszl<9:8> | imm3<7:5> | Zdn<4:0>
260
261
USE(zn);
262
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
263
VIXL_ASSERT(zd.Is(zn));
264
265
Instr encoded_imm =
266
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
267
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSL_z_p_zi);
268
}
269
270
void Assembler::lsl(const ZRegister& zd,
271
const PRegisterM& pg,
272
const ZRegister& zn,
273
const ZRegister& zm) {
274
// LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
275
// 0000 0100 ..01 1011 100. .... .... ....
276
// size<23:22> | R<18> = 0 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
277
// Zdn<4:0>
278
279
USE(zn);
280
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
281
VIXL_ASSERT(zd.Is(zn));
282
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
283
((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
284
(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
285
Instr op = LSL_z_p_zw;
286
if (AreSameLaneSize(zd, zn, zm)) {
287
op = LSL_z_p_zz;
288
}
289
Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
290
}
291
292
void Assembler::lslr(const ZRegister& zd,
293
const PRegisterM& pg,
294
const ZRegister& zn,
295
const ZRegister& zm) {
296
// LSLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
297
// 0000 0100 ..01 0111 100. .... .... ....
298
// size<23:22> | R<18> = 1 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
299
// Zdn<4:0>
300
301
USE(zn);
302
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
303
VIXL_ASSERT(zd.Is(zn));
304
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
305
306
Emit(LSLR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
307
}
308
309
void Assembler::lsr(const ZRegister& zd,
310
const PRegisterM& pg,
311
const ZRegister& zn,
312
int shift) {
313
// LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
314
// 0000 0100 ..00 0001 100. .... .... ....
315
// tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 1 | Pg<12:10> |
316
// tszl<9:8> | imm3<7:5> | Zdn<4:0>
317
318
USE(zn);
319
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
320
VIXL_ASSERT(zd.Is(zn));
321
322
Instr encoded_imm =
323
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
324
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSR_z_p_zi);
325
}
326
327
void Assembler::lsr(const ZRegister& zd,
328
const PRegisterM& pg,
329
const ZRegister& zn,
330
const ZRegister& zm) {
331
// LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D
332
// 0000 0100 ..01 1001 100. .... .... ....
333
// size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
334
// Zdn<4:0>
335
336
USE(zn);
337
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
338
VIXL_ASSERT(zd.Is(zn));
339
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||
340
((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&
341
(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));
342
Instr op = LSR_z_p_zw;
343
if (AreSameLaneSize(zd, zn, zm)) {
344
op = LSR_z_p_zz;
345
}
346
Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
347
}
348
349
void Assembler::lsrr(const ZRegister& zd,
350
const PRegisterM& pg,
351
const ZRegister& zn,
352
const ZRegister& zm) {
353
// LSRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
354
// 0000 0100 ..01 0101 100. .... .... ....
355
// size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |
356
// Zdn<4:0>
357
358
USE(zn);
359
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
360
VIXL_ASSERT(zd.Is(zn));
361
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
362
363
Emit(LSRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
364
}
365
366
// SVEBitwiseShiftUnpredicated.
367
368
Instr Assembler::EncodeSVEShiftLeftImmediate(int shift, int lane_size_in_bits) {
369
VIXL_ASSERT((shift >= 0) && (shift < lane_size_in_bits));
370
return lane_size_in_bits + shift;
371
}
372
373
Instr Assembler::EncodeSVEShiftRightImmediate(int shift,
374
int lane_size_in_bits) {
375
VIXL_ASSERT((shift > 0) && (shift <= lane_size_in_bits));
376
return (2 * lane_size_in_bits) - shift;
377
}
378
379
void Assembler::SVEBitwiseShiftImmediate(const ZRegister& zd,
380
const ZRegister& zn,
381
Instr encoded_imm_and_tsz,
382
Instr op) {
383
Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)
384
<< 16;
385
Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;
386
Emit(op | tszh | tszl_and_imm | Rd(zd) | Rn(zn));
387
}
388
389
void Assembler::asr(const ZRegister& zd, const ZRegister& zn, int shift) {
390
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
391
VIXL_ASSERT(AreSameLaneSize(zd, zn));
392
Instr encoded_imm =
393
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
394
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, ASR_z_zi);
395
}
396
397
void Assembler::asr(const ZRegister& zd,
398
const ZRegister& zn,
399
const ZRegister& zm) {
400
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
401
VIXL_ASSERT(AreSameLaneSize(zd, zn));
402
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
403
404
Emit(ASR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
405
}
406
407
void Assembler::lsl(const ZRegister& zd, const ZRegister& zn, int shift) {
408
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
409
Instr encoded_imm =
410
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
411
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSL_z_zi);
412
}
413
414
void Assembler::lsl(const ZRegister& zd,
415
const ZRegister& zn,
416
const ZRegister& zm) {
417
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
418
VIXL_ASSERT(AreSameLaneSize(zd, zn));
419
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
420
421
Emit(LSL_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
422
}
423
424
void Assembler::lsr(const ZRegister& zd, const ZRegister& zn, int shift) {
425
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
426
Instr encoded_imm =
427
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
428
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSR_z_zi);
429
}
430
431
void Assembler::lsr(const ZRegister& zd,
432
const ZRegister& zn,
433
const ZRegister& zm) {
434
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
435
VIXL_ASSERT(AreSameLaneSize(zd, zn));
436
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);
437
438
Emit(LSR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
439
}
440
441
// SVEElementCount.
442
443
#define VIXL_SVE_INC_DEC_LIST(V) \
444
V(cntb, CNTB_r_s) \
445
V(cnth, CNTH_r_s) \
446
V(cntw, CNTW_r_s) \
447
V(cntd, CNTD_r_s) \
448
V(decb, DECB_r_rs) \
449
V(dech, DECH_r_rs) \
450
V(decw, DECW_r_rs) \
451
V(decd, DECD_r_rs) \
452
V(incb, INCB_r_rs) \
453
V(inch, INCH_r_rs) \
454
V(incw, INCW_r_rs) \
455
V(incd, INCD_r_rs) \
456
V(sqdecb, SQDECB_r_rs_x) \
457
V(sqdech, SQDECH_r_rs_x) \
458
V(sqdecw, SQDECW_r_rs_x) \
459
V(sqdecd, SQDECD_r_rs_x) \
460
V(sqincb, SQINCB_r_rs_x) \
461
V(sqinch, SQINCH_r_rs_x) \
462
V(sqincw, SQINCW_r_rs_x) \
463
V(sqincd, SQINCD_r_rs_x)
464
465
#define VIXL_DEFINE_ASM_FUNC(FN, OP) \
466
void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \
467
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
468
VIXL_ASSERT(rdn.IsX()); \
469
Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) | \
470
ImmUnsignedField<19, 16>(multiplier - 1)); \
471
}
472
VIXL_SVE_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)
473
#undef VIXL_DEFINE_ASM_FUNC
474
475
#define VIXL_SVE_UQINC_UQDEC_LIST(V) \
476
V(uqdecb, (rdn.IsX() ? UQDECB_r_rs_x : UQDECB_r_rs_uw)) \
477
V(uqdech, (rdn.IsX() ? UQDECH_r_rs_x : UQDECH_r_rs_uw)) \
478
V(uqdecw, (rdn.IsX() ? UQDECW_r_rs_x : UQDECW_r_rs_uw)) \
479
V(uqdecd, (rdn.IsX() ? UQDECD_r_rs_x : UQDECD_r_rs_uw)) \
480
V(uqincb, (rdn.IsX() ? UQINCB_r_rs_x : UQINCB_r_rs_uw)) \
481
V(uqinch, (rdn.IsX() ? UQINCH_r_rs_x : UQINCH_r_rs_uw)) \
482
V(uqincw, (rdn.IsX() ? UQINCW_r_rs_x : UQINCW_r_rs_uw)) \
483
V(uqincd, (rdn.IsX() ? UQINCD_r_rs_x : UQINCD_r_rs_uw))
484
485
#define VIXL_DEFINE_ASM_FUNC(FN, OP) \
486
void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \
487
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
488
Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) | \
489
ImmUnsignedField<19, 16>(multiplier - 1)); \
490
}
491
VIXL_SVE_UQINC_UQDEC_LIST(VIXL_DEFINE_ASM_FUNC)
492
#undef VIXL_DEFINE_ASM_FUNC
493
494
#define VIXL_SVE_SQX_INC_DEC_LIST(V) \
495
V(sqdecb, SQDECB) \
496
V(sqdech, SQDECH) \
497
V(sqdecw, SQDECW) \
498
V(sqdecd, SQDECD) \
499
V(sqincb, SQINCB) \
500
V(sqinch, SQINCH) \
501
V(sqincw, SQINCW) \
502
V(sqincd, SQINCD)
503
504
#define VIXL_DEFINE_ASM_FUNC(FN, OP) \
505
void Assembler::FN(const Register& xd, \
506
const Register& wn, \
507
int pattern, \
508
int multiplier) { \
509
USE(wn); \
510
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
511
VIXL_ASSERT(wn.IsW() && xd.Is(wn.X())); \
512
Emit(OP##_r_rs_sx | Rd(xd) | ImmSVEPredicateConstraint(pattern) | \
513
ImmUnsignedField<19, 16>(multiplier - 1)); \
514
}
515
VIXL_SVE_SQX_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)
516
#undef VIXL_DEFINE_ASM_FUNC
517
518
#define VIXL_SVE_INC_DEC_VEC_LIST(V) \
519
V(dech, DEC, H) \
520
V(decw, DEC, W) \
521
V(decd, DEC, D) \
522
V(inch, INC, H) \
523
V(incw, INC, W) \
524
V(incd, INC, D) \
525
V(sqdech, SQDEC, H) \
526
V(sqdecw, SQDEC, W) \
527
V(sqdecd, SQDEC, D) \
528
V(sqinch, SQINC, H) \
529
V(sqincw, SQINC, W) \
530
V(sqincd, SQINC, D) \
531
V(uqdech, UQDEC, H) \
532
V(uqdecw, UQDEC, W) \
533
V(uqdecd, UQDEC, D) \
534
V(uqinch, UQINC, H) \
535
V(uqincw, UQINC, W) \
536
V(uqincd, UQINC, D)
537
538
#define VIXL_DEFINE_ASM_FUNC(FN, OP, T) \
539
void Assembler::FN(const ZRegister& zdn, int pattern, int multiplier) { \
540
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
541
VIXL_ASSERT(zdn.GetLaneSizeInBytes() == k##T##RegSizeInBytes); \
542
Emit(OP##T##_z_zs | Rd(zdn) | ImmSVEPredicateConstraint(pattern) | \
543
ImmUnsignedField<19, 16>(multiplier - 1)); \
544
}
545
VIXL_SVE_INC_DEC_VEC_LIST(VIXL_DEFINE_ASM_FUNC)
546
#undef VIXL_DEFINE_ASM_FUNC
547
548
// SVEFPAccumulatingReduction.
549
550
void Assembler::fadda(const VRegister& vd,
551
const PRegister& pg,
552
const VRegister& vn,
553
const ZRegister& zm) {
554
// FADDA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
555
// 0110 0101 ..01 1000 001. .... .... ....
556
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
557
558
USE(vn);
559
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
560
VIXL_ASSERT(vd.Is(vn));
561
VIXL_ASSERT(vd.IsScalar());
562
VIXL_ASSERT(zm.GetLaneSizeInBytes() != kBRegSizeInBytes);
563
VIXL_ASSERT(AreSameLaneSize(zm, vd));
564
565
Emit(FADDA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
566
}
567
568
// SVEFPArithmetic_Predicated.
569
570
void Assembler::fabd(const ZRegister& zd,
571
const PRegisterM& pg,
572
const ZRegister& zn,
573
const ZRegister& zm) {
574
// FABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
575
// 0110 0101 ..00 1000 100. .... .... ....
576
// size<23:22> | opc<19:16> = 1000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
577
578
USE(zn);
579
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
580
VIXL_ASSERT(zd.Is(zn));
581
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
582
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
583
584
Emit(FABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
585
}
586
587
void Assembler::fadd(const ZRegister& zd,
588
const PRegisterM& pg,
589
const ZRegister& zn,
590
double imm) {
591
// FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
592
// 0110 0101 ..01 1000 100. ..00 00.. ....
593
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | i1<5> | Zdn<4:0>
594
595
USE(zn);
596
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
597
VIXL_ASSERT(zd.Is(zn));
598
VIXL_ASSERT(AreSameLaneSize(zd, zn));
599
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
600
VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
601
602
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
603
Emit(FADD_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
604
}
605
606
void Assembler::fadd(const ZRegister& zd,
607
const PRegisterM& pg,
608
const ZRegister& zn,
609
const ZRegister& zm) {
610
// FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
611
// 0110 0101 ..00 0000 100. .... .... ....
612
// size<23:22> | opc<19:16> = 0000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
613
614
USE(zn);
615
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
616
VIXL_ASSERT(zd.Is(zn));
617
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
618
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
619
620
Emit(FADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
621
}
622
623
void Assembler::fdiv(const ZRegister& zd,
624
const PRegisterM& pg,
625
const ZRegister& zn,
626
const ZRegister& zm) {
627
// FDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
628
// 0110 0101 ..00 1101 100. .... .... ....
629
// size<23:22> | opc<19:16> = 1101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
630
631
USE(zn);
632
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
633
VIXL_ASSERT(zd.Is(zn));
634
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
635
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
636
637
Emit(FDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
638
}
639
640
void Assembler::fdivr(const ZRegister& zd,
641
const PRegisterM& pg,
642
const ZRegister& zn,
643
const ZRegister& zm) {
644
// FDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
645
// 0110 0101 ..00 1100 100. .... .... ....
646
// size<23:22> | opc<19:16> = 1100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
647
648
USE(zn);
649
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
650
VIXL_ASSERT(zd.Is(zn));
651
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
652
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
653
654
Emit(FDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
655
}
656
657
void Assembler::fmax(const ZRegister& zd,
658
const PRegisterM& pg,
659
const ZRegister& zn,
660
double imm) {
661
// FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
662
// 0110 0101 ..01 1110 100. ..00 00.. ....
663
// size<23:22> | opc<18:16> = 110 | Pg<12:10> | i1<5> | Zdn<4:0>
664
665
USE(zn);
666
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
667
VIXL_ASSERT(zd.Is(zn));
668
VIXL_ASSERT(AreSameLaneSize(zd, zn));
669
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
670
VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
671
672
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
673
Emit(FMAX_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
674
}
675
676
void Assembler::fmax(const ZRegister& zd,
677
const PRegisterM& pg,
678
const ZRegister& zn,
679
const ZRegister& zm) {
680
// FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
681
// 0110 0101 ..00 0110 100. .... .... ....
682
// size<23:22> | opc<19:16> = 0110 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
683
684
USE(zn);
685
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
686
VIXL_ASSERT(zd.Is(zn));
687
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
688
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
689
690
Emit(FMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
691
}
692
693
void Assembler::fmaxnm(const ZRegister& zd,
694
const PRegisterM& pg,
695
const ZRegister& zn,
696
double imm) {
697
// FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
698
// 0110 0101 ..01 1100 100. ..00 00.. ....
699
// size<23:22> | opc<18:16> = 100 | Pg<12:10> | i1<5> | Zdn<4:0>
700
701
USE(zn);
702
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
703
VIXL_ASSERT(zd.Is(zn));
704
VIXL_ASSERT(AreSameLaneSize(zd, zn));
705
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
706
VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
707
708
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
709
Emit(FMAXNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
710
}
711
712
void Assembler::fmaxnm(const ZRegister& zd,
713
const PRegisterM& pg,
714
const ZRegister& zn,
715
const ZRegister& zm) {
716
// FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
717
// 0110 0101 ..00 0100 100. .... .... ....
718
// size<23:22> | opc<19:16> = 0100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
719
720
USE(zn);
721
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
722
VIXL_ASSERT(zd.Is(zn));
723
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
724
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
725
726
Emit(FMAXNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
727
}
728
729
void Assembler::fmin(const ZRegister& zd,
730
const PRegisterM& pg,
731
const ZRegister& zn,
732
double imm) {
733
// FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
734
// 0110 0101 ..01 1111 100. ..00 00.. ....
735
// size<23:22> | opc<18:16> = 111 | Pg<12:10> | i1<5> | Zdn<4:0>
736
737
USE(zn);
738
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
739
VIXL_ASSERT(zd.Is(zn));
740
VIXL_ASSERT(AreSameLaneSize(zd, zn));
741
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
742
VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
743
744
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
745
Emit(FMIN_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
746
}
747
748
void Assembler::fmin(const ZRegister& zd,
749
const PRegisterM& pg,
750
const ZRegister& zn,
751
const ZRegister& zm) {
752
// FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
753
// 0110 0101 ..00 0111 100. .... .... ....
754
// size<23:22> | opc<19:16> = 0111 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
755
756
USE(zn);
757
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
758
VIXL_ASSERT(zd.Is(zn));
759
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
760
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
761
762
Emit(FMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
763
}
764
765
void Assembler::fminnm(const ZRegister& zd,
766
const PRegisterM& pg,
767
const ZRegister& zn,
768
double imm) {
769
// FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
770
// 0110 0101 ..01 1101 100. ..00 00.. ....
771
// size<23:22> | opc<18:16> = 101 | Pg<12:10> | i1<5> | Zdn<4:0>
772
773
USE(zn);
774
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
775
VIXL_ASSERT(zd.Is(zn));
776
VIXL_ASSERT(AreSameLaneSize(zd, zn));
777
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
778
VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));
779
780
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
781
Emit(FMINNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
782
}
783
784
void Assembler::fminnm(const ZRegister& zd,
785
const PRegisterM& pg,
786
const ZRegister& zn,
787
const ZRegister& zm) {
788
// FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
789
// 0110 0101 ..00 0101 100. .... .... ....
790
// size<23:22> | opc<19:16> = 0101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
791
792
USE(zn);
793
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
794
VIXL_ASSERT(zd.Is(zn));
795
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
796
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
797
798
Emit(FMINNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
799
}
800
801
void Assembler::fmul(const ZRegister& zd,
802
const PRegisterM& pg,
803
const ZRegister& zn,
804
double imm) {
805
// FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
806
// 0110 0101 ..01 1010 100. ..00 00.. ....
807
// size<23:22> | opc<18:16> = 010 | Pg<12:10> | i1<5> | Zdn<4:0>
808
809
USE(zn);
810
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
811
VIXL_ASSERT(zd.Is(zn));
812
VIXL_ASSERT(AreSameLaneSize(zd, zn));
813
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
814
VIXL_ASSERT((imm == 0.5) || (imm == 2.0));
815
816
Instr i1 = (imm == 2.0) ? (1 << 5) : 0;
817
Emit(FMUL_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
818
}
819
820
void Assembler::fmul(const ZRegister& zd,
821
const PRegisterM& pg,
822
const ZRegister& zn,
823
const ZRegister& zm) {
824
// FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
825
// 0110 0101 ..00 0010 100. .... .... ....
826
// size<23:22> | opc<19:16> = 0010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
827
828
USE(zn);
829
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
830
VIXL_ASSERT(zd.Is(zn));
831
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
832
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
833
834
Emit(FMUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
835
}
836
837
void Assembler::fmulx(const ZRegister& zd,
838
const PRegisterM& pg,
839
const ZRegister& zn,
840
const ZRegister& zm) {
841
// FMULX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
842
// 0110 0101 ..00 1010 100. .... .... ....
843
// size<23:22> | opc<19:16> = 1010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
844
845
USE(zn);
846
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
847
VIXL_ASSERT(zd.Is(zn));
848
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
849
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
850
851
Emit(FMULX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
852
}
853
854
void Assembler::fscale(const ZRegister& zd,
855
const PRegisterM& pg,
856
const ZRegister& zn,
857
const ZRegister& zm) {
858
// FSCALE <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
859
// 0110 0101 ..00 1001 100. .... .... ....
860
// size<23:22> | opc<19:16> = 1001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
861
862
USE(zn);
863
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
864
VIXL_ASSERT(zd.Is(zn));
865
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
866
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
867
868
Emit(FSCALE_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
869
}
870
871
void Assembler::fsub(const ZRegister& zd,
872
const PRegisterM& pg,
873
const ZRegister& zn,
874
double imm) {
875
// FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
876
// 0110 0101 ..01 1001 100. ..00 00.. ....
877
// size<23:22> | opc<18:16> = 001 | Pg<12:10> | i1<5> | Zdn<4:0>
878
879
USE(zn);
880
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
881
VIXL_ASSERT(zd.Is(zn));
882
VIXL_ASSERT(AreSameLaneSize(zd, zn));
883
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
884
VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
885
886
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
887
Emit(FSUB_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
888
}
889
890
void Assembler::fsub(const ZRegister& zd,
891
const PRegisterM& pg,
892
const ZRegister& zn,
893
const ZRegister& zm) {
894
// FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
895
// 0110 0101 ..00 0001 100. .... .... ....
896
// size<23:22> | opc<19:16> = 0001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
897
898
USE(zn);
899
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
900
VIXL_ASSERT(zd.Is(zn));
901
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
902
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
903
904
Emit(FSUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
905
}
906
907
void Assembler::fsubr(const ZRegister& zd,
908
const PRegisterM& pg,
909
const ZRegister& zn,
910
double imm) {
911
// FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>
912
// 0110 0101 ..01 1011 100. ..00 00.. ....
913
// size<23:22> | opc<18:16> = 011 | Pg<12:10> | i1<5> | Zdn<4:0>
914
915
USE(zn);
916
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
917
VIXL_ASSERT(zd.Is(zn));
918
VIXL_ASSERT(AreSameLaneSize(zd, zn));
919
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
920
VIXL_ASSERT((imm == 0.5) || (imm == 1.0));
921
922
Instr i1 = (imm == 1.0) ? (1 << 5) : 0;
923
Emit(FSUBR_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);
924
}
925
926
void Assembler::fsubr(const ZRegister& zd,
927
const PRegisterM& pg,
928
const ZRegister& zn,
929
const ZRegister& zm) {
930
// FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
931
// 0110 0101 ..00 0011 100. .... .... ....
932
// size<23:22> | opc<19:16> = 0011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
933
934
USE(zn);
935
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
936
VIXL_ASSERT(zd.Is(zn));
937
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
938
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
939
940
Emit(FSUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
941
}
942
943
void Assembler::ftmad(const ZRegister& zd,
944
const ZRegister& zn,
945
const ZRegister& zm,
946
int imm3) {
947
// FTMAD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<imm>
948
// 0110 0101 ..01 0... 1000 00.. .... ....
949
// size<23:22> | imm3<18:16> | Zm<9:5> | Zdn<4:0>
950
951
USE(zn);
952
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
953
VIXL_ASSERT(zd.Is(zn));
954
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
955
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
956
957
Emit(FTMAD_z_zzi | SVESize(zd) | Rd(zd) | Rn(zm) |
958
ImmUnsignedField<18, 16>(imm3));
959
}
960
961
// SVEFPArithmeticUnpredicated.
962
963
void Assembler::fadd(const ZRegister& zd,
964
const ZRegister& zn,
965
const ZRegister& zm) {
966
// FADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
967
// 0110 0101 ..0. .... 0000 00.. .... ....
968
// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
969
970
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
971
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
972
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
973
974
Emit(FADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
975
}
976
977
void Assembler::fmul(const ZRegister& zd,
978
const ZRegister& zn,
979
const ZRegister& zm) {
980
// FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
981
// 0110 0101 ..0. .... 0000 10.. .... ....
982
// size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>
983
984
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
985
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
986
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
987
988
Emit(FMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
989
}
990
991
void Assembler::frecps(const ZRegister& zd,
992
const ZRegister& zn,
993
const ZRegister& zm) {
994
// FRECPS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
995
// 0110 0101 ..0. .... 0001 10.. .... ....
996
// size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>
997
998
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
999
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1000
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1001
1002
Emit(FRECPS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1003
}
1004
1005
void Assembler::frsqrts(const ZRegister& zd,
1006
const ZRegister& zn,
1007
const ZRegister& zm) {
1008
// FRSQRTS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1009
// 0110 0101 ..0. .... 0001 11.. .... ....
1010
// size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>
1011
1012
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1013
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1014
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1015
1016
Emit(FRSQRTS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1017
}
1018
1019
void Assembler::fsub(const ZRegister& zd,
1020
const ZRegister& zn,
1021
const ZRegister& zm) {
1022
// FSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1023
// 0110 0101 ..0. .... 0000 01.. .... ....
1024
// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
1025
1026
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1027
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1028
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1029
1030
Emit(FSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1031
}
1032
1033
void Assembler::ftsmul(const ZRegister& zd,
1034
const ZRegister& zn,
1035
const ZRegister& zm) {
1036
// FTSMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
1037
// 0110 0101 ..0. .... 0000 11.. .... ....
1038
// size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>
1039
1040
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1041
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1042
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1043
1044
Emit(FTSMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
1045
}
1046
1047
// SVEFPCompareVectors.
1048
1049
void Assembler::facge(const PRegisterWithLaneSize& pd,
1050
const PRegisterZ& pg,
1051
const ZRegister& zn,
1052
const ZRegister& zm) {
1053
// FACGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1054
// 0110 0101 ..0. .... 110. .... ...1 ....
1055
// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1056
// o3<4> = 1 | Pd<3:0>
1057
1058
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1059
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1060
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1061
1062
Emit(FACGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1063
}
1064
1065
void Assembler::facgt(const PRegisterWithLaneSize& pd,
1066
const PRegisterZ& pg,
1067
const ZRegister& zn,
1068
const ZRegister& zm) {
1069
// FACGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1070
// 0110 0101 ..0. .... 111. .... ...1 ....
1071
// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1072
// o3<4> = 1 | Pd<3:0>
1073
1074
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1075
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1076
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1077
1078
Emit(FACGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1079
}
1080
1081
void Assembler::fcmeq(const PRegisterWithLaneSize& pd,
1082
const PRegisterZ& pg,
1083
const ZRegister& zn,
1084
const ZRegister& zm) {
1085
// FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1086
// 0110 0101 ..0. .... 011. .... ...0 ....
1087
// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1088
// o3<4> = 0 | Pd<3:0>
1089
1090
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1091
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1092
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1093
1094
Emit(FCMEQ_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1095
}
1096
1097
void Assembler::fcmge(const PRegisterWithLaneSize& pd,
1098
const PRegisterZ& pg,
1099
const ZRegister& zn,
1100
const ZRegister& zm) {
1101
// FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1102
// 0110 0101 ..0. .... 010. .... ...0 ....
1103
// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1104
// o3<4> = 0 | Pd<3:0>
1105
1106
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1107
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1108
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1109
1110
Emit(FCMGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1111
}
1112
1113
void Assembler::fcmgt(const PRegisterWithLaneSize& pd,
1114
const PRegisterZ& pg,
1115
const ZRegister& zn,
1116
const ZRegister& zm) {
1117
// FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1118
// 0110 0101 ..0. .... 010. .... ...1 ....
1119
// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1120
// o3<4> = 1 | Pd<3:0>
1121
1122
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1123
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1124
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1125
1126
Emit(FCMGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1127
}
1128
1129
void Assembler::fcmne(const PRegisterWithLaneSize& pd,
1130
const PRegisterZ& pg,
1131
const ZRegister& zn,
1132
const ZRegister& zm) {
1133
// FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1134
// 0110 0101 ..0. .... 011. .... ...1 ....
1135
// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |
1136
// o3<4> = 1 | Pd<3:0>
1137
1138
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1139
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1140
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1141
1142
Emit(FCMNE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1143
}
1144
1145
void Assembler::fcmuo(const PRegisterWithLaneSize& pd,
1146
const PRegisterZ& pg,
1147
const ZRegister& zn,
1148
const ZRegister& zm) {
1149
// FCMUO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
1150
// 0110 0101 ..0. .... 110. .... ...0 ....
1151
// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |
1152
// o3<4> = 0 | Pd<3:0>
1153
1154
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1155
VIXL_ASSERT(AreSameLaneSize(zn, zm));
1156
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1157
1158
Emit(FCMUO_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
1159
}
1160
1161
// SVEFPCompareWithZero.
1162
1163
void Assembler::fcmeq(const PRegisterWithLaneSize& pd,
1164
const PRegisterZ& pg,
1165
const ZRegister& zn,
1166
double zero) {
1167
// FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1168
// 0110 0101 ..01 0010 001. .... ...0 ....
1169
// size<23:22> | eq<17> = 1 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1170
// Pd<3:0>
1171
1172
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1173
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1174
VIXL_ASSERT(zero == 0.0);
1175
USE(zero);
1176
1177
Emit(FCMEQ_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1178
}
1179
1180
void Assembler::fcmge(const PRegisterWithLaneSize& pd,
1181
const PRegisterZ& pg,
1182
const ZRegister& zn,
1183
double zero) {
1184
// FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1185
// 0110 0101 ..01 0000 001. .... ...0 ....
1186
// size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1187
// Pd<3:0>
1188
1189
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1190
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1191
VIXL_ASSERT(zero == 0.0);
1192
USE(zero);
1193
1194
Emit(FCMGE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1195
}
1196
1197
void Assembler::fcmgt(const PRegisterWithLaneSize& pd,
1198
const PRegisterZ& pg,
1199
const ZRegister& zn,
1200
double zero) {
1201
// FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1202
// 0110 0101 ..01 0000 001. .... ...1 ....
1203
// size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
1204
// Pd<3:0>
1205
1206
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1207
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1208
VIXL_ASSERT(zero == 0.0);
1209
USE(zero);
1210
1211
Emit(FCMGT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1212
}
1213
1214
void Assembler::fcmle(const PRegisterWithLaneSize& pd,
1215
const PRegisterZ& pg,
1216
const ZRegister& zn,
1217
double zero) {
1218
// FCMLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1219
// 0110 0101 ..01 0001 001. .... ...1 ....
1220
// size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
1221
// Pd<3:0>
1222
1223
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1224
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1225
VIXL_ASSERT(zero == 0.0);
1226
USE(zero);
1227
1228
Emit(FCMLE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1229
}
1230
1231
void Assembler::fcmlt(const PRegisterWithLaneSize& pd,
1232
const PRegisterZ& pg,
1233
const ZRegister& zn,
1234
double zero) {
1235
// FCMLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1236
// 0110 0101 ..01 0001 001. .... ...0 ....
1237
// size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1238
// Pd<3:0>
1239
1240
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1241
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1242
VIXL_ASSERT(zero == 0.0);
1243
USE(zero);
1244
1245
Emit(FCMLT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1246
}
1247
1248
void Assembler::fcmne(const PRegisterWithLaneSize& pd,
1249
const PRegisterZ& pg,
1250
const ZRegister& zn,
1251
double zero) {
1252
// FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
1253
// 0110 0101 ..01 0011 001. .... ...0 ....
1254
// size<23:22> | eq<17> = 1 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
1255
// Pd<3:0>
1256
1257
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1258
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1259
VIXL_ASSERT(zero == 0.0);
1260
USE(zero);
1261
1262
Emit(FCMNE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));
1263
}
1264
1265
// SVEFPComplexAddition.
1266
1267
void Assembler::fcadd(const ZRegister& zd,
1268
const PRegisterM& pg,
1269
const ZRegister& zn,
1270
const ZRegister& zm,
1271
int rot) {
1272
// FCADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>, <const>
1273
// 0110 0100 ..00 000. 100. .... .... ....
1274
// size<23:22> | rot<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1275
1276
USE(zn);
1277
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1278
VIXL_ASSERT(zd.Is(zn));
1279
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1280
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1281
VIXL_ASSERT((rot == 90) || (rot == 270));
1282
1283
Instr rotate_bit = (rot == 90) ? 0 : (1 << 16);
1284
Emit(FCADD_z_p_zz | rotate_bit | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
1285
}
1286
1287
// SVEFPComplexMulAdd.
1288
1289
void Assembler::fcmla(const ZRegister& zda,
1290
const PRegisterM& pg,
1291
const ZRegister& zn,
1292
const ZRegister& zm,
1293
int rot) {
1294
// FCMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>, <const>
1295
// 0110 0100 ..0. .... 0... .... .... ....
1296
// size<23:22> | Zm<20:16> | rot<14:13> | Pg<12:10> | Zn<9:5> | Zda<4:0>
1297
1298
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1299
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1300
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1301
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
1302
1303
Instr rotate_bit = (rot / 90) << 13;
1304
Emit(FCMLA_z_p_zzz | rotate_bit | SVESize(zda) | Rd(zda) | PgLow8(pg) |
1305
Rn(zn) | Rm(zm));
1306
}
1307
1308
// SVEFPComplexMulAddIndex.
1309
1310
void Assembler::fcmla(const ZRegister& zda,
1311
const ZRegister& zn,
1312
const ZRegister& zm,
1313
int index,
1314
int rot) {
1315
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1316
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1317
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
1318
1319
Instr rotate_bit = (rot / 90) << 10;
1320
Emit(FCMLA_z_zzzi_h | SVEMulComplexIndexHelper(zm, index) | rotate_bit |
1321
Rd(zda) | Rn(zn));
1322
}
1323
1324
// SVEFPFastReduction.
1325
1326
void Assembler::faddv(const VRegister& vd,
1327
const PRegister& pg,
1328
const ZRegister& zn) {
1329
// FADDV <V><d>, <Pg>, <Zn>.<T>
1330
// 0110 0101 ..00 0000 001. .... .... ....
1331
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1332
1333
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1334
VIXL_ASSERT(vd.IsScalar());
1335
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1336
VIXL_ASSERT(AreSameLaneSize(zn, vd));
1337
1338
Emit(FADDV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1339
}
1340
1341
void Assembler::fmaxnmv(const VRegister& vd,
1342
const PRegister& pg,
1343
const ZRegister& zn) {
1344
// FMAXNMV <V><d>, <Pg>, <Zn>.<T>
1345
// 0110 0101 ..00 0100 001. .... .... ....
1346
// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1347
1348
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1349
VIXL_ASSERT(vd.IsScalar());
1350
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1351
VIXL_ASSERT(AreSameLaneSize(zn, vd));
1352
1353
Emit(FMAXNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1354
}
1355
1356
void Assembler::fmaxv(const VRegister& vd,
1357
const PRegister& pg,
1358
const ZRegister& zn) {
1359
// FMAXV <V><d>, <Pg>, <Zn>.<T>
1360
// 0110 0101 ..00 0110 001. .... .... ....
1361
// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1362
1363
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1364
VIXL_ASSERT(vd.IsScalar());
1365
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1366
VIXL_ASSERT(AreSameLaneSize(zn, vd));
1367
1368
Emit(FMAXV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1369
}
1370
1371
void Assembler::fminnmv(const VRegister& vd,
1372
const PRegister& pg,
1373
const ZRegister& zn) {
1374
// FMINNMV <V><d>, <Pg>, <Zn>.<T>
1375
// 0110 0101 ..00 0101 001. .... .... ....
1376
// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1377
1378
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1379
VIXL_ASSERT(vd.IsScalar());
1380
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1381
VIXL_ASSERT(AreSameLaneSize(zn, vd));
1382
1383
Emit(FMINNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1384
}
1385
1386
void Assembler::fminv(const VRegister& vd,
1387
const PRegister& pg,
1388
const ZRegister& zn) {
1389
// FMINV <V><d>, <Pg>, <Zn>.<T>
1390
// 0110 0101 ..00 0111 001. .... .... ....
1391
// size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Vd<4:0>
1392
1393
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1394
VIXL_ASSERT(vd.IsScalar());
1395
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1396
VIXL_ASSERT(AreSameLaneSize(zn, vd));
1397
1398
Emit(FMINV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
1399
}
1400
1401
// SVEFPMulAdd.
1402
1403
void Assembler::fmad(const ZRegister& zdn,
1404
const PRegisterM& pg,
1405
const ZRegister& zm,
1406
const ZRegister& za) {
1407
// FMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1408
// 0110 0101 ..1. .... 100. .... .... ....
1409
// size<23:22> | Za<20:16> | opc<14:13> = 00 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1410
1411
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1412
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1413
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1414
1415
Emit(FMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1416
}
1417
1418
void Assembler::fmla(const ZRegister& zda,
1419
const PRegisterM& pg,
1420
const ZRegister& zn,
1421
const ZRegister& zm) {
1422
// FMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1423
// 0110 0101 ..1. .... 000. .... .... ....
1424
// size<23:22> | Zm<20:16> | opc<14:13> = 00 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1425
1426
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1427
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1428
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1429
1430
Emit(FMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1431
}
1432
1433
void Assembler::fmls(const ZRegister& zda,
1434
const PRegisterM& pg,
1435
const ZRegister& zn,
1436
const ZRegister& zm) {
1437
// FMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1438
// 0110 0101 ..1. .... 001. .... .... ....
1439
// size<23:22> | Zm<20:16> | opc<14:13> = 01 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1440
1441
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1442
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1443
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1444
1445
Emit(FMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1446
}
1447
1448
void Assembler::fmsb(const ZRegister& zdn,
1449
const PRegisterM& pg,
1450
const ZRegister& zm,
1451
const ZRegister& za) {
1452
// FMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1453
// 0110 0101 ..1. .... 101. .... .... ....
1454
// size<23:22> | Za<20:16> | opc<14:13> = 01 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1455
1456
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1457
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1458
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1459
1460
Emit(FMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1461
}
1462
1463
void Assembler::fnmad(const ZRegister& zdn,
1464
const PRegisterM& pg,
1465
const ZRegister& zm,
1466
const ZRegister& za) {
1467
// FNMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1468
// 0110 0101 ..1. .... 110. .... .... ....
1469
// size<23:22> | Za<20:16> | opc<14:13> = 10 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1470
1471
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1472
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1473
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1474
1475
Emit(FNMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1476
}
1477
1478
void Assembler::fnmla(const ZRegister& zda,
1479
const PRegisterM& pg,
1480
const ZRegister& zn,
1481
const ZRegister& zm) {
1482
// FNMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1483
// 0110 0101 ..1. .... 010. .... .... ....
1484
// size<23:22> | Zm<20:16> | opc<14:13> = 10 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1485
1486
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1487
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1488
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1489
1490
Emit(FNMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1491
}
1492
1493
void Assembler::fnmls(const ZRegister& zda,
1494
const PRegisterM& pg,
1495
const ZRegister& zn,
1496
const ZRegister& zm) {
1497
// FNMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
1498
// 0110 0101 ..1. .... 011. .... .... ....
1499
// size<23:22> | Zm<20:16> | opc<14:13> = 11 | Pg<12:10> | Zn<9:5> | Zda<4:0>
1500
1501
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1502
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1503
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
1504
1505
Emit(FNMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
1506
}
1507
1508
void Assembler::fnmsb(const ZRegister& zdn,
1509
const PRegisterM& pg,
1510
const ZRegister& zm,
1511
const ZRegister& za) {
1512
// FNMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
1513
// 0110 0101 ..1. .... 111. .... .... ....
1514
// size<23:22> | Za<20:16> | opc<14:13> = 11 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
1515
1516
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1517
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
1518
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
1519
1520
Emit(FNMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));
1521
}
1522
1523
Instr Assembler::SVEMulIndexHelper(unsigned lane_size_in_bytes_log2,
1524
const ZRegister& zm,
1525
int index,
1526
Instr op_h,
1527
Instr op_s,
1528
Instr op_d) {
1529
Instr size = lane_size_in_bytes_log2 << SVESize_offset;
1530
Instr zm_with_index = Rm(zm);
1531
Instr op = 0xffffffff;
1532
// Allowable register number and lane index depends on the lane size.
1533
switch (lane_size_in_bytes_log2) {
1534
case kHRegSizeInBytesLog2:
1535
VIXL_ASSERT(zm.GetCode() <= 7);
1536
VIXL_ASSERT(IsUint3(index));
1537
// For H-sized lanes, size is encoded as 0b0x, where x is used as the top
1538
// bit of the index. So, if index is less than four, the top bit of index
1539
// is zero, and therefore size is 0b00. Otherwise, it's 0b01, the usual
1540
// encoding for H-sized lanes.
1541
if (index < 4) size = 0;
1542
// Top two bits of "zm" encode the index.
1543
zm_with_index |= (index & 3) << (Rm_offset + 3);
1544
op = op_h;
1545
break;
1546
case kSRegSizeInBytesLog2:
1547
VIXL_CHECK(zm.GetCode() <= 7);
1548
VIXL_CHECK(IsUint2(index));
1549
// Top two bits of "zm" encode the index.
1550
zm_with_index |= (index & 3) << (Rm_offset + 3);
1551
op = op_s;
1552
break;
1553
case kDRegSizeInBytesLog2:
1554
VIXL_CHECK(zm.GetCode() <= 15);
1555
VIXL_CHECK(IsUint1(index));
1556
// Top bit of "zm" encodes the index.
1557
zm_with_index |= (index & 1) << (Rm_offset + 4);
1558
op = op_d;
1559
break;
1560
default:
1561
VIXL_UNIMPLEMENTED();
1562
}
1563
return op | zm_with_index | size;
1564
}
1565
1566
Instr Assembler::SVEMulLongIndexHelper(const ZRegister& zm, int index) {
1567
Instr imm_field;
1568
Instr zm_id;
1569
if (zm.IsLaneSizeH()) {
1570
VIXL_CHECK(zm.GetCode() <= 7);
1571
VIXL_CHECK(IsUint3(index));
1572
imm_field = ExtractUnsignedBitfield32(2, 1, index) << 19;
1573
zm_id = Rx<18, 16>(zm);
1574
} else {
1575
VIXL_ASSERT(zm.IsLaneSizeS());
1576
VIXL_CHECK(zm.GetCode() <= 15);
1577
VIXL_CHECK(IsUint2(index));
1578
imm_field = ExtractBit(index, 1) << 20;
1579
zm_id = Rx<19, 16>(zm);
1580
}
1581
1582
// Synthesize the low part of immediate encoding.
1583
imm_field |= ExtractBit(index, 0) << 11;
1584
1585
return zm_id | imm_field;
1586
}
1587
1588
Instr Assembler::SVEMulComplexIndexHelper(const ZRegister& zm, int index) {
1589
Instr zm_idx_size;
1590
if (zm.IsLaneSizeH()) {
1591
// Zm<18:16> | i2<20:19>
1592
VIXL_CHECK(zm.GetCode() <= 7);
1593
VIXL_CHECK(IsUint2(index));
1594
zm_idx_size = (index << 19) | Rx<18, 16>(zm) | 0;
1595
} else {
1596
VIXL_ASSERT(zm.IsLaneSizeS());
1597
// Zm<19:16> | i1<20>
1598
VIXL_CHECK(zm.GetCode() <= 15);
1599
VIXL_CHECK(IsUint1(index));
1600
zm_idx_size = (index << 20) | Rx<19, 16>(zm) | (1 << 22);
1601
}
1602
return zm_idx_size;
1603
}
1604
1605
// SVEFPMulAddIndex.
1606
1607
void Assembler::fmla(const ZRegister& zda,
1608
const ZRegister& zn,
1609
const ZRegister& zm,
1610
int index) {
1611
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1612
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1613
1614
// The encoding of opcode, index, Zm, and size are synthesized in this
1615
// variable.
1616
Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
1617
zm,
1618
index,
1619
FMLA_z_zzzi_h,
1620
FMLA_z_zzzi_s,
1621
FMLA_z_zzzi_d);
1622
1623
Emit(synthesized_op | Rd(zda) | Rn(zn));
1624
}
1625
1626
void Assembler::fmls(const ZRegister& zda,
1627
const ZRegister& zn,
1628
const ZRegister& zm,
1629
int index) {
1630
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1631
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
1632
1633
// The encoding of opcode, index, Zm, and size are synthesized in this
1634
// variable.
1635
Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
1636
zm,
1637
index,
1638
FMLS_z_zzzi_h,
1639
FMLS_z_zzzi_s,
1640
FMLS_z_zzzi_d);
1641
1642
Emit(synthesized_op | Rd(zda) | Rn(zn));
1643
}
1644
1645
// SVEFPMulIndex.
1646
1647
// This prototype maps to 3 instruction encodings:
1648
void Assembler::fmul(const ZRegister& zd,
1649
const ZRegister& zn,
1650
const ZRegister& zm,
1651
unsigned index) {
1652
// FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>[<imm>]
1653
// 0110 0100 ..1. .... 0010 00.. .... ....
1654
// size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>
1655
1656
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1657
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
1658
1659
// The encoding of opcode, index, Zm, and size are synthesized in this
1660
// variable.
1661
Instr synthesized_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
1662
zm,
1663
index,
1664
FMUL_z_zzi_h,
1665
FMUL_z_zzi_s,
1666
FMUL_z_zzi_d);
1667
1668
Emit(synthesized_op | Rd(zd) | Rn(zn));
1669
}
1670
1671
// SVEFPUnaryOpPredicated.
1672
1673
void Assembler::fcvt(const ZRegister& zd,
1674
const PRegisterM& pg,
1675
const ZRegister& zn) {
1676
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1677
1678
Instr op = 0xffffffff;
1679
switch (zn.GetLaneSizeInBytes()) {
1680
case kHRegSizeInBytes:
1681
switch (zd.GetLaneSizeInBytes()) {
1682
case kSRegSizeInBytes:
1683
op = FCVT_z_p_z_h2s;
1684
break;
1685
case kDRegSizeInBytes:
1686
op = FCVT_z_p_z_h2d;
1687
break;
1688
}
1689
break;
1690
case kSRegSizeInBytes:
1691
switch (zd.GetLaneSizeInBytes()) {
1692
case kHRegSizeInBytes:
1693
op = FCVT_z_p_z_s2h;
1694
break;
1695
case kDRegSizeInBytes:
1696
op = FCVT_z_p_z_s2d;
1697
break;
1698
}
1699
break;
1700
case kDRegSizeInBytes:
1701
switch (zd.GetLaneSizeInBytes()) {
1702
case kHRegSizeInBytes:
1703
op = FCVT_z_p_z_d2h;
1704
break;
1705
case kSRegSizeInBytes:
1706
op = FCVT_z_p_z_d2s;
1707
break;
1708
}
1709
break;
1710
}
1711
VIXL_ASSERT(op != 0xffffffff);
1712
1713
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1714
}
1715
1716
void Assembler::fcvtzs(const ZRegister& zd,
1717
const PRegisterM& pg,
1718
const ZRegister& zn) {
1719
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1720
Instr op = 0xffffffff;
1721
switch (zn.GetLaneSizeInBytes()) {
1722
case kHRegSizeInBytes:
1723
switch (zd.GetLaneSizeInBytes()) {
1724
case kHRegSizeInBytes:
1725
op = FCVTZS_z_p_z_fp162h;
1726
break;
1727
case kSRegSizeInBytes:
1728
op = FCVTZS_z_p_z_fp162w;
1729
break;
1730
case kDRegSizeInBytes:
1731
op = FCVTZS_z_p_z_fp162x;
1732
break;
1733
}
1734
break;
1735
case kSRegSizeInBytes:
1736
switch (zd.GetLaneSizeInBytes()) {
1737
case kSRegSizeInBytes:
1738
op = FCVTZS_z_p_z_s2w;
1739
break;
1740
case kDRegSizeInBytes:
1741
op = FCVTZS_z_p_z_s2x;
1742
break;
1743
}
1744
break;
1745
case kDRegSizeInBytes:
1746
switch (zd.GetLaneSizeInBytes()) {
1747
case kSRegSizeInBytes:
1748
op = FCVTZS_z_p_z_d2w;
1749
break;
1750
case kDRegSizeInBytes:
1751
op = FCVTZS_z_p_z_d2x;
1752
break;
1753
}
1754
break;
1755
}
1756
VIXL_ASSERT(op != 0xffffffff);
1757
1758
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1759
}
1760
1761
void Assembler::fcvtzu(const ZRegister& zd,
1762
const PRegisterM& pg,
1763
const ZRegister& zn) {
1764
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1765
Instr op = 0xffffffff;
1766
switch (zn.GetLaneSizeInBytes()) {
1767
case kHRegSizeInBytes:
1768
switch (zd.GetLaneSizeInBytes()) {
1769
case kHRegSizeInBytes:
1770
op = FCVTZU_z_p_z_fp162h;
1771
break;
1772
case kSRegSizeInBytes:
1773
op = FCVTZU_z_p_z_fp162w;
1774
break;
1775
case kDRegSizeInBytes:
1776
op = FCVTZU_z_p_z_fp162x;
1777
break;
1778
}
1779
break;
1780
case kSRegSizeInBytes:
1781
switch (zd.GetLaneSizeInBytes()) {
1782
case kSRegSizeInBytes:
1783
op = FCVTZU_z_p_z_s2w;
1784
break;
1785
case kDRegSizeInBytes:
1786
op = FCVTZU_z_p_z_s2x;
1787
break;
1788
}
1789
break;
1790
case kDRegSizeInBytes:
1791
switch (zd.GetLaneSizeInBytes()) {
1792
case kSRegSizeInBytes:
1793
op = FCVTZU_z_p_z_d2w;
1794
break;
1795
case kDRegSizeInBytes:
1796
op = FCVTZU_z_p_z_d2x;
1797
break;
1798
}
1799
break;
1800
}
1801
VIXL_ASSERT(op != 0xffffffff);
1802
1803
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1804
}
1805
1806
void Assembler::frecpx(const ZRegister& zd,
1807
const PRegisterM& pg,
1808
const ZRegister& zn) {
1809
// FRECPX <Zd>.<T>, <Pg>/M, <Zn>.<T>
1810
// 0110 0101 ..00 1100 101. .... .... ....
1811
// size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>
1812
1813
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1814
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1815
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1816
1817
Emit(FRECPX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1818
}
1819
1820
void Assembler::frinta(const ZRegister& zd,
1821
const PRegisterM& pg,
1822
const ZRegister& zn) {
1823
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1824
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1825
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1826
1827
Emit(FRINTA_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1828
}
1829
1830
void Assembler::frinti(const ZRegister& zd,
1831
const PRegisterM& pg,
1832
const ZRegister& zn) {
1833
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1834
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1835
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1836
1837
Emit(FRINTI_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1838
}
1839
1840
void Assembler::frintm(const ZRegister& zd,
1841
const PRegisterM& pg,
1842
const ZRegister& zn) {
1843
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1844
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1845
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1846
1847
Emit(FRINTM_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1848
}
1849
1850
void Assembler::frintn(const ZRegister& zd,
1851
const PRegisterM& pg,
1852
const ZRegister& zn) {
1853
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1854
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1855
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1856
1857
Emit(FRINTN_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1858
}
1859
1860
void Assembler::frintp(const ZRegister& zd,
1861
const PRegisterM& pg,
1862
const ZRegister& zn) {
1863
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1864
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1865
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1866
1867
Emit(FRINTP_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1868
}
1869
1870
void Assembler::frintx(const ZRegister& zd,
1871
const PRegisterM& pg,
1872
const ZRegister& zn) {
1873
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1874
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1875
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1876
1877
Emit(FRINTX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1878
}
1879
1880
void Assembler::frintz(const ZRegister& zd,
1881
const PRegisterM& pg,
1882
const ZRegister& zn) {
1883
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1884
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1885
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1886
1887
Emit(FRINTZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1888
}
1889
1890
void Assembler::fsqrt(const ZRegister& zd,
1891
const PRegisterM& pg,
1892
const ZRegister& zn) {
1893
// FSQRT <Zd>.<T>, <Pg>/M, <Zn>.<T>
1894
// 0110 0101 ..00 1101 101. .... .... ....
1895
// size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>
1896
1897
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1898
VIXL_ASSERT(AreSameLaneSize(zd, zn));
1899
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
1900
1901
Emit(FSQRT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
1902
}
1903
1904
void Assembler::scvtf(const ZRegister& zd,
1905
const PRegisterM& pg,
1906
const ZRegister& zn) {
1907
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1908
Instr op = 0xffffffff;
1909
switch (zn.GetLaneSizeInBytes()) {
1910
case kHRegSizeInBytes:
1911
switch (zd.GetLaneSizeInBytes()) {
1912
case kHRegSizeInBytes:
1913
op = SCVTF_z_p_z_h2fp16;
1914
break;
1915
}
1916
break;
1917
case kSRegSizeInBytes:
1918
switch (zd.GetLaneSizeInBytes()) {
1919
case kHRegSizeInBytes:
1920
op = SCVTF_z_p_z_w2fp16;
1921
break;
1922
case kSRegSizeInBytes:
1923
op = SCVTF_z_p_z_w2s;
1924
break;
1925
case kDRegSizeInBytes:
1926
op = SCVTF_z_p_z_w2d;
1927
break;
1928
}
1929
break;
1930
case kDRegSizeInBytes:
1931
switch (zd.GetLaneSizeInBytes()) {
1932
case kHRegSizeInBytes:
1933
op = SCVTF_z_p_z_x2fp16;
1934
break;
1935
case kSRegSizeInBytes:
1936
op = SCVTF_z_p_z_x2s;
1937
break;
1938
case kDRegSizeInBytes:
1939
op = SCVTF_z_p_z_x2d;
1940
break;
1941
}
1942
break;
1943
}
1944
VIXL_ASSERT(op != 0xffffffff);
1945
1946
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1947
}
1948
1949
void Assembler::ucvtf(const ZRegister& zd,
1950
const PRegisterM& pg,
1951
const ZRegister& zn) {
1952
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
1953
Instr op = 0xffffffff;
1954
switch (zn.GetLaneSizeInBytes()) {
1955
case kHRegSizeInBytes:
1956
switch (zd.GetLaneSizeInBytes()) {
1957
case kHRegSizeInBytes:
1958
op = UCVTF_z_p_z_h2fp16;
1959
break;
1960
}
1961
break;
1962
case kSRegSizeInBytes:
1963
switch (zd.GetLaneSizeInBytes()) {
1964
case kHRegSizeInBytes:
1965
op = UCVTF_z_p_z_w2fp16;
1966
break;
1967
case kSRegSizeInBytes:
1968
op = UCVTF_z_p_z_w2s;
1969
break;
1970
case kDRegSizeInBytes:
1971
op = UCVTF_z_p_z_w2d;
1972
break;
1973
}
1974
break;
1975
case kDRegSizeInBytes:
1976
switch (zd.GetLaneSizeInBytes()) {
1977
case kHRegSizeInBytes:
1978
op = UCVTF_z_p_z_x2fp16;
1979
break;
1980
case kSRegSizeInBytes:
1981
op = UCVTF_z_p_z_x2s;
1982
break;
1983
case kDRegSizeInBytes:
1984
op = UCVTF_z_p_z_x2d;
1985
break;
1986
}
1987
break;
1988
}
1989
VIXL_ASSERT(op != 0xffffffff);
1990
1991
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
1992
}
1993
1994
// SVEFPUnaryOpUnpredicated.
1995
1996
void Assembler::frecpe(const ZRegister& zd, const ZRegister& zn) {
1997
// FRECPE <Zd>.<T>, <Zn>.<T>
1998
// 0110 0101 ..00 1110 0011 00.. .... ....
1999
// size<23:22> | opc<18:16> = 110 | Zn<9:5> | Zd<4:0>
2000
2001
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2002
VIXL_ASSERT(AreSameLaneSize(zd, zn));
2003
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
2004
2005
Emit(FRECPE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
2006
}
2007
2008
void Assembler::frsqrte(const ZRegister& zd, const ZRegister& zn) {
2009
// FRSQRTE <Zd>.<T>, <Zn>.<T>
2010
// 0110 0101 ..00 1111 0011 00.. .... ....
2011
// size<23:22> | opc<18:16> = 111 | Zn<9:5> | Zd<4:0>
2012
2013
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2014
VIXL_ASSERT(AreSameLaneSize(zd, zn));
2015
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
2016
2017
Emit(FRSQRTE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
2018
}
2019
2020
// SVEIncDecByPredicateCount.
2021
2022
void Assembler::decp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2023
// DECP <Xdn>, <Pg>.<T>
2024
// 0010 0101 ..10 1101 1000 100. .... ....
2025
// size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |
2026
// Rdn<4:0>
2027
2028
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2029
VIXL_ASSERT(rdn.IsX());
2030
2031
Emit(DECP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2032
}
2033
2034
void Assembler::decp(const ZRegister& zdn, const PRegister& pg) {
2035
// DECP <Zdn>.<T>, <Pg>
2036
// 0010 0101 ..10 1101 1000 000. .... ....
2037
// size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |
2038
// Zdn<4:0>
2039
2040
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2041
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2042
VIXL_ASSERT(pg.IsUnqualified());
2043
2044
Emit(DECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2045
}
2046
2047
void Assembler::incp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2048
// INCP <Xdn>, <Pg>.<T>
2049
// 0010 0101 ..10 1100 1000 100. .... ....
2050
// size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |
2051
// Rdn<4:0>
2052
2053
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2054
VIXL_ASSERT(rdn.IsX());
2055
2056
Emit(INCP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2057
}
2058
2059
void Assembler::incp(const ZRegister& zdn, const PRegister& pg) {
2060
// INCP <Zdn>.<T>, <Pg>
2061
// 0010 0101 ..10 1100 1000 000. .... ....
2062
// size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |
2063
// Zdn<4:0>
2064
2065
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2066
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2067
VIXL_ASSERT(pg.IsUnqualified());
2068
2069
Emit(INCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2070
}
2071
2072
void Assembler::sqdecp(const Register& xd,
2073
const PRegisterWithLaneSize& pg,
2074
const Register& wn) {
2075
// SQDECP <Xdn>, <Pg>.<T>, <Wdn>
2076
// 0010 0101 ..10 1010 1000 100. .... ....
2077
// size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2078
// Rdn<4:0>
2079
2080
USE(wn);
2081
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2082
VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));
2083
2084
Emit(SQDECP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));
2085
}
2086
2087
void Assembler::sqdecp(const Register& xdn, const PRegisterWithLaneSize& pg) {
2088
// SQDECP <Xdn>, <Pg>.<T>
2089
// 0010 0101 ..10 1010 1000 110. .... ....
2090
// size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |
2091
// Rdn<4:0>
2092
2093
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2094
VIXL_ASSERT(xdn.IsX());
2095
2096
Emit(SQDECP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));
2097
}
2098
2099
void Assembler::sqdecp(const ZRegister& zdn, const PRegister& pg) {
2100
// SQDECP <Zdn>.<T>, <Pg>
2101
// 0010 0101 ..10 1010 1000 000. .... ....
2102
// size<23:22> | D<17> = 1 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2103
2104
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2105
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2106
VIXL_ASSERT(pg.IsUnqualified());
2107
2108
Emit(SQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2109
}
2110
2111
void Assembler::sqincp(const Register& xd,
2112
const PRegisterWithLaneSize& pg,
2113
const Register& wn) {
2114
// SQINCP <Xdn>, <Pg>.<T>, <Wdn>
2115
// 0010 0101 ..10 1000 1000 100. .... ....
2116
// size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2117
// Rdn<4:0>
2118
2119
USE(wn);
2120
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2121
VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));
2122
2123
Emit(SQINCP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));
2124
}
2125
2126
void Assembler::sqincp(const Register& xdn, const PRegisterWithLaneSize& pg) {
2127
// SQINCP <Xdn>, <Pg>.<T>
2128
// 0010 0101 ..10 1000 1000 110. .... ....
2129
// size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |
2130
// Rdn<4:0>
2131
2132
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2133
VIXL_ASSERT(xdn.IsX());
2134
2135
Emit(SQINCP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));
2136
}
2137
2138
void Assembler::sqincp(const ZRegister& zdn, const PRegister& pg) {
2139
// SQINCP <Zdn>.<T>, <Pg>
2140
// 0010 0101 ..10 1000 1000 000. .... ....
2141
// size<23:22> | D<17> = 0 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2142
2143
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2144
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2145
VIXL_ASSERT(pg.IsUnqualified());
2146
2147
Emit(SQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2148
}
2149
2150
void Assembler::uqdecp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2151
// UQDECP <Wdn>, <Pg>.<T>
2152
// UQDECP <Xdn>, <Pg>.<T>
2153
// 0010 0101 ..10 1011 1000 10.. .... ....
2154
// size<23:22> | D<17> = 1 | U<16> = 1 | sf<10> | op<9> = 0 | Pg<8:5> |
2155
// Rdn<4:0>
2156
2157
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2158
2159
Instr op = rdn.IsX() ? UQDECP_r_p_r_x : UQDECP_r_p_r_uw;
2160
Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2161
}
2162
2163
void Assembler::uqdecp(const ZRegister& zdn, const PRegister& pg) {
2164
// UQDECP <Zdn>.<T>, <Pg>
2165
// 0010 0101 ..10 1011 1000 000. .... ....
2166
// size<23:22> | D<17> = 1 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2167
2168
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2169
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2170
VIXL_ASSERT(pg.IsUnqualified());
2171
2172
Emit(UQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2173
}
2174
2175
void Assembler::uqincp(const Register& rdn, const PRegisterWithLaneSize& pg) {
2176
// UQINCP <Wdn>, <Pg>.<T>
2177
// 0010 0101 ..10 1001 1000 100. .... ....
2178
// size<23:22> | D<17> = 0 | U<16> = 1 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |
2179
// Rdn<4:0>
2180
2181
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2182
2183
Instr op = rdn.IsX() ? UQINCP_r_p_r_x : UQINCP_r_p_r_uw;
2184
Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));
2185
}
2186
2187
void Assembler::uqincp(const ZRegister& zdn, const PRegister& pg) {
2188
// UQINCP <Zdn>.<T>, <Pg>
2189
// 0010 0101 ..10 1001 1000 000. .... ....
2190
// size<23:22> | D<17> = 0 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>
2191
2192
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2193
VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);
2194
VIXL_ASSERT(pg.IsUnqualified());
2195
2196
Emit(UQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));
2197
}
2198
2199
// SVEIndexGeneration.
2200
2201
void Assembler::index(const ZRegister& zd, int start, int step) {
2202
// INDEX <Zd>.<T>, #<imm1>, #<imm2>
2203
// 0000 0100 ..1. .... 0100 00.. .... ....
2204
// size<23:22> | step<20:16> | start<9:5> | Zd<4:0>
2205
2206
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2207
2208
Emit(INDEX_z_ii | SVESize(zd) | ImmField<20, 16>(step) |
2209
ImmField<9, 5>(start) | Rd(zd));
2210
}
2211
2212
void Assembler::index(const ZRegister& zd,
2213
const Register& rn,
2214
const Register& rm) {
2215
// INDEX <Zd>.<T>, <R><n>, <R><m>
2216
// 0000 0100 ..1. .... 0100 11.. .... ....
2217
// size<23:22> | Rm<20:16> | Rn<9:5> | Zd<4:0>
2218
2219
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2220
VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
2221
zd.GetLaneSizeInBits());
2222
VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=
2223
zd.GetLaneSizeInBits());
2224
2225
Emit(INDEX_z_rr | SVESize(zd) | Rd(zd) | Rn(rn) | Rm(rm));
2226
}
2227
2228
void Assembler::index(const ZRegister& zd, const Register& rn, int imm5) {
2229
// INDEX <Zd>.<T>, <R><n>, #<imm>
2230
// 0000 0100 ..1. .... 0100 01.. .... ....
2231
// size<23:22> | imm5<20:16> | Rn<9:5> | Zd<4:0>
2232
2233
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2234
VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
2235
zd.GetLaneSizeInBits());
2236
2237
Emit(INDEX_z_ri | SVESize(zd) | Rd(zd) | Rn(rn) | ImmField<20, 16>(imm5));
2238
}
2239
2240
void Assembler::index(const ZRegister& zd, int imm5, const Register& rm) {
2241
// INDEX <Zd>.<T>, #<imm>, <R><m>
2242
// 0000 0100 ..1. .... 0100 10.. .... ....
2243
// size<23:22> | Rm<20:16> | imm5<9:5> | Zd<4:0>
2244
2245
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2246
VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=
2247
zd.GetLaneSizeInBits());
2248
2249
Emit(INDEX_z_ir | SVESize(zd) | Rd(zd) | ImmField<9, 5>(imm5) | Rm(rm));
2250
}
2251
2252
// SVEIntArithmeticUnpredicated.
2253
2254
void Assembler::add(const ZRegister& zd,
2255
const ZRegister& zn,
2256
const ZRegister& zm) {
2257
// ADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2258
// 0000 0100 ..1. .... 0000 00.. .... ....
2259
// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
2260
2261
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2262
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2263
2264
Emit(ADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2265
}
2266
2267
void Assembler::sqadd(const ZRegister& zd,
2268
const ZRegister& zn,
2269
const ZRegister& zm) {
2270
// SQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2271
// 0000 0100 ..1. .... 0001 00.. .... ....
2272
// size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>
2273
2274
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2275
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2276
2277
Emit(SQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2278
}
2279
2280
void Assembler::sqsub(const ZRegister& zd,
2281
const ZRegister& zn,
2282
const ZRegister& zm) {
2283
// SQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2284
// 0000 0100 ..1. .... 0001 10.. .... ....
2285
// size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>
2286
2287
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2288
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2289
2290
Emit(SQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2291
}
2292
2293
void Assembler::sub(const ZRegister& zd,
2294
const ZRegister& zn,
2295
const ZRegister& zm) {
2296
// SUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2297
// 0000 0100 ..1. .... 0000 01.. .... ....
2298
// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
2299
2300
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2301
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2302
2303
Emit(SUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2304
}
2305
2306
void Assembler::uqadd(const ZRegister& zd,
2307
const ZRegister& zn,
2308
const ZRegister& zm) {
2309
// UQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2310
// 0000 0100 ..1. .... 0001 01.. .... ....
2311
// size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>
2312
2313
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2314
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2315
2316
Emit(UQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2317
}
2318
2319
void Assembler::uqsub(const ZRegister& zd,
2320
const ZRegister& zn,
2321
const ZRegister& zm) {
2322
// UQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
2323
// 0000 0100 ..1. .... 0001 11.. .... ....
2324
// size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>
2325
2326
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2327
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
2328
2329
Emit(UQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
2330
}
2331
2332
// SVEIntBinaryArithmeticPredicated.
2333
2334
void Assembler::add(const ZRegister& zd,
2335
const PRegisterM& pg,
2336
const ZRegister& zn,
2337
const ZRegister& zm) {
2338
// ADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2339
// 0000 0100 ..00 0000 000. .... .... ....
2340
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2341
2342
USE(zn);
2343
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2344
VIXL_ASSERT(zd.Is(zn));
2345
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2346
2347
Emit(ADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2348
}
2349
2350
void Assembler::and_(const ZRegister& zd,
2351
const PRegisterM& pg,
2352
const ZRegister& zn,
2353
const ZRegister& zm) {
2354
// AND <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2355
// 0000 0100 ..01 1010 000. .... .... ....
2356
// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2357
2358
USE(zn);
2359
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2360
VIXL_ASSERT(zd.Is(zn));
2361
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2362
2363
Emit(AND_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2364
}
2365
2366
void Assembler::bic(const ZRegister& zd,
2367
const PRegisterM& pg,
2368
const ZRegister& zn,
2369
const ZRegister& zm) {
2370
// BIC <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2371
// 0000 0100 ..01 1011 000. .... .... ....
2372
// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2373
2374
USE(zn);
2375
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2376
VIXL_ASSERT(zd.Is(zn));
2377
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2378
2379
Emit(BIC_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2380
}
2381
2382
void Assembler::eor(const ZRegister& zd,
2383
const PRegisterM& pg,
2384
const ZRegister& zn,
2385
const ZRegister& zm) {
2386
// EOR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2387
// 0000 0100 ..01 1001 000. .... .... ....
2388
// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2389
2390
USE(zn);
2391
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2392
VIXL_ASSERT(zd.Is(zn));
2393
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2394
2395
Emit(EOR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2396
}
2397
2398
void Assembler::mul(const ZRegister& zd,
2399
const PRegisterM& pg,
2400
const ZRegister& zn,
2401
const ZRegister& zm) {
2402
// MUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2403
// 0000 0100 ..01 0000 000. .... .... ....
2404
// size<23:22> | H<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2405
2406
USE(zn);
2407
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2408
VIXL_ASSERT(zd.Is(zn));
2409
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2410
2411
Emit(MUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2412
}
2413
2414
void Assembler::orr(const ZRegister& zd,
2415
const PRegisterM& pg,
2416
const ZRegister& zn,
2417
const ZRegister& zm) {
2418
// ORR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2419
// 0000 0100 ..01 1000 000. .... .... ....
2420
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2421
2422
USE(zn);
2423
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2424
VIXL_ASSERT(zd.Is(zn));
2425
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2426
2427
Emit(ORR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2428
}
2429
2430
void Assembler::sabd(const ZRegister& zd,
2431
const PRegisterM& pg,
2432
const ZRegister& zn,
2433
const ZRegister& zm) {
2434
// SABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2435
// 0000 0100 ..00 1100 000. .... .... ....
2436
// size<23:22> | opc<18:17> = 10 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2437
2438
USE(zn);
2439
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2440
VIXL_ASSERT(zd.Is(zn));
2441
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2442
2443
Emit(SABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2444
}
2445
2446
void Assembler::sdiv(const ZRegister& zd,
2447
const PRegisterM& pg,
2448
const ZRegister& zn,
2449
const ZRegister& zm) {
2450
// SDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2451
// 0000 0100 ..01 0100 000. .... .... ....
2452
// size<23:22> | R<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2453
2454
USE(zn);
2455
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2456
VIXL_ASSERT(zd.Is(zn));
2457
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2458
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2459
2460
Emit(SDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2461
}
2462
2463
void Assembler::sdivr(const ZRegister& zd,
2464
const PRegisterM& pg,
2465
const ZRegister& zn,
2466
const ZRegister& zm) {
2467
// SDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2468
// 0000 0100 ..01 0110 000. .... .... ....
2469
// size<23:22> | R<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2470
2471
USE(zn);
2472
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2473
VIXL_ASSERT(zd.Is(zn));
2474
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2475
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2476
2477
Emit(SDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2478
}
2479
2480
void Assembler::smax(const ZRegister& zd,
2481
const PRegisterM& pg,
2482
const ZRegister& zn,
2483
const ZRegister& zm) {
2484
// SMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2485
// 0000 0100 ..00 1000 000. .... .... ....
2486
// size<23:22> | opc<18:17> = 00 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2487
2488
USE(zn);
2489
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2490
VIXL_ASSERT(zd.Is(zn));
2491
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2492
2493
Emit(SMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2494
}
2495
2496
void Assembler::smin(const ZRegister& zd,
2497
const PRegisterM& pg,
2498
const ZRegister& zn,
2499
const ZRegister& zm) {
2500
// SMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2501
// 0000 0100 ..00 1010 000. .... .... ....
2502
// size<23:22> | opc<18:17> = 01 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2503
2504
USE(zn);
2505
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2506
VIXL_ASSERT(zd.Is(zn));
2507
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2508
2509
Emit(SMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2510
}
2511
2512
void Assembler::smulh(const ZRegister& zd,
2513
const PRegisterM& pg,
2514
const ZRegister& zn,
2515
const ZRegister& zm) {
2516
// SMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2517
// 0000 0100 ..01 0010 000. .... .... ....
2518
// size<23:22> | H<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2519
2520
USE(zn);
2521
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2522
VIXL_ASSERT(zd.Is(zn));
2523
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2524
2525
Emit(SMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2526
}
2527
2528
void Assembler::sub(const ZRegister& zd,
2529
const PRegisterM& pg,
2530
const ZRegister& zn,
2531
const ZRegister& zm) {
2532
// SUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2533
// 0000 0100 ..00 0001 000. .... .... ....
2534
// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2535
2536
USE(zn);
2537
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2538
VIXL_ASSERT(zd.Is(zn));
2539
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2540
2541
Emit(SUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2542
}
2543
2544
void Assembler::subr(const ZRegister& zd,
2545
const PRegisterM& pg,
2546
const ZRegister& zn,
2547
const ZRegister& zm) {
2548
// SUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2549
// 0000 0100 ..00 0011 000. .... .... ....
2550
// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2551
2552
USE(zn);
2553
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2554
VIXL_ASSERT(zd.Is(zn));
2555
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2556
2557
Emit(SUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2558
}
2559
2560
void Assembler::uabd(const ZRegister& zd,
2561
const PRegisterM& pg,
2562
const ZRegister& zn,
2563
const ZRegister& zm) {
2564
// UABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2565
// 0000 0100 ..00 1101 000. .... .... ....
2566
// size<23:22> | opc<18:17> = 10 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2567
2568
USE(zn);
2569
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2570
VIXL_ASSERT(zd.Is(zn));
2571
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2572
2573
Emit(UABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2574
}
2575
2576
void Assembler::udiv(const ZRegister& zd,
2577
const PRegisterM& pg,
2578
const ZRegister& zn,
2579
const ZRegister& zm) {
2580
// UDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2581
// 0000 0100 ..01 0101 000. .... .... ....
2582
// size<23:22> | R<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2583
2584
USE(zn);
2585
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2586
VIXL_ASSERT(zd.Is(zn));
2587
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2588
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2589
2590
Emit(UDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2591
}
2592
2593
void Assembler::udivr(const ZRegister& zd,
2594
const PRegisterM& pg,
2595
const ZRegister& zn,
2596
const ZRegister& zm) {
2597
// UDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2598
// 0000 0100 ..01 0111 000. .... .... ....
2599
// size<23:22> | R<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2600
2601
USE(zn);
2602
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2603
VIXL_ASSERT(zd.Is(zn));
2604
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2605
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
2606
2607
Emit(UDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2608
}
2609
2610
void Assembler::umax(const ZRegister& zd,
2611
const PRegisterM& pg,
2612
const ZRegister& zn,
2613
const ZRegister& zm) {
2614
// UMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2615
// 0000 0100 ..00 1001 000. .... .... ....
2616
// size<23:22> | opc<18:17> = 00 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2617
2618
USE(zn);
2619
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2620
VIXL_ASSERT(zd.Is(zn));
2621
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2622
2623
Emit(UMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2624
}
2625
2626
void Assembler::umin(const ZRegister& zd,
2627
const PRegisterM& pg,
2628
const ZRegister& zn,
2629
const ZRegister& zm) {
2630
// UMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2631
// 0000 0100 ..00 1011 000. .... .... ....
2632
// size<23:22> | opc<18:17> = 01 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2633
2634
USE(zn);
2635
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2636
VIXL_ASSERT(zd.Is(zn));
2637
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2638
2639
Emit(UMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2640
}
2641
2642
void Assembler::umulh(const ZRegister& zd,
2643
const PRegisterM& pg,
2644
const ZRegister& zn,
2645
const ZRegister& zm) {
2646
// UMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
2647
// 0000 0100 ..01 0011 000. .... .... ....
2648
// size<23:22> | H<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
2649
2650
USE(zn);
2651
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2652
VIXL_ASSERT(zd.Is(zn));
2653
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
2654
2655
Emit(UMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
2656
}
2657
2658
// SVEIntCompareScalars.
2659
2660
void Assembler::ctermeq(const Register& rn, const Register& rm) {
2661
// CTERMEQ <R><n>, <R><m>
2662
// 0010 0101 1.1. .... 0010 00.. ...0 0000
2663
// op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 0
2664
2665
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2666
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2667
const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;
2668
2669
Emit(CTERMEQ_rr | sz | Rn(rn) | Rm(rm));
2670
}
2671
2672
void Assembler::ctermne(const Register& rn, const Register& rm) {
2673
// CTERMNE <R><n>, <R><m>
2674
// 0010 0101 1.1. .... 0010 00.. ...1 0000
2675
// op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 1
2676
2677
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2678
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2679
const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;
2680
2681
Emit(CTERMNE_rr | sz | Rn(rn) | Rm(rm));
2682
}
2683
2684
void Assembler::whilele(const PRegisterWithLaneSize& pd,
2685
const Register& rn,
2686
const Register& rm) {
2687
// WHILELE <Pd>.<T>, <R><n>, <R><m>
2688
// 0010 0101 ..1. .... 000. 01.. ...1 ....
2689
// size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |
2690
// eq<4> = 1 | Pd<3:0>
2691
2692
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2693
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2694
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2695
2696
Emit(WHILELE_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2697
}
2698
2699
void Assembler::whilelo(const PRegisterWithLaneSize& pd,
2700
const Register& rn,
2701
const Register& rm) {
2702
// WHILELO <Pd>.<T>, <R><n>, <R><m>
2703
// 0010 0101 ..1. .... 000. 11.. ...0 ....
2704
// size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |
2705
// eq<4> = 0 | Pd<3:0>
2706
2707
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2708
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2709
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2710
2711
Emit(WHILELO_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2712
}
2713
2714
void Assembler::whilels(const PRegisterWithLaneSize& pd,
2715
const Register& rn,
2716
const Register& rm) {
2717
// WHILELS <Pd>.<T>, <R><n>, <R><m>
2718
// 0010 0101 ..1. .... 000. 11.. ...1 ....
2719
// size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |
2720
// eq<4> = 1 | Pd<3:0>
2721
2722
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2723
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2724
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2725
2726
Emit(WHILELS_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2727
}
2728
2729
void Assembler::whilelt(const PRegisterWithLaneSize& pd,
2730
const Register& rn,
2731
const Register& rm) {
2732
// WHILELT <Pd>.<T>, <R><n>, <R><m>
2733
// 0010 0101 ..1. .... 000. 01.. ...0 ....
2734
// size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |
2735
// eq<4> = 0 | Pd<3:0>
2736
2737
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2738
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
2739
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
2740
2741
Emit(WHILELT_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
2742
}
2743
2744
void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2745
const PRegisterZ& pg,
2746
const ZRegister& zn,
2747
const ZRegister& zm,
2748
SVEIntCompareVectorsOp op) {
2749
Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
2750
}
2751
2752
void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2753
const PRegisterZ& pg,
2754
const ZRegister& zn,
2755
int imm,
2756
SVEIntCompareSignedImmOp op) {
2757
Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm));
2758
}
2759
2760
void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,
2761
const PRegisterZ& pg,
2762
const ZRegister& zn,
2763
unsigned imm,
2764
SVEIntCompareUnsignedImmOp op) {
2765
Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) |
2766
ImmUnsignedField<20, 14>(imm));
2767
}
2768
2769
void Assembler::cmp(Condition cond,
2770
const PRegisterWithLaneSize& pd,
2771
const PRegisterZ& pg,
2772
const ZRegister& zn,
2773
const ZRegister& zm) {
2774
switch (cond) {
2775
case eq:
2776
cmpeq(pd, pg, zn, zm);
2777
break;
2778
case ge:
2779
cmpge(pd, pg, zn, zm);
2780
break;
2781
case gt:
2782
cmpgt(pd, pg, zn, zm);
2783
break;
2784
case le:
2785
cmple(pd, pg, zn, zm);
2786
break;
2787
case lt:
2788
cmplt(pd, pg, zn, zm);
2789
break;
2790
case ne:
2791
cmpne(pd, pg, zn, zm);
2792
break;
2793
case hi:
2794
cmphi(pd, pg, zn, zm);
2795
break;
2796
case hs:
2797
cmphs(pd, pg, zn, zm);
2798
break;
2799
case lo:
2800
cmplo(pd, pg, zn, zm);
2801
break;
2802
case ls:
2803
cmpls(pd, pg, zn, zm);
2804
break;
2805
default:
2806
VIXL_UNREACHABLE();
2807
}
2808
}
2809
2810
// SVEIntCompareSignedImm.
2811
2812
void Assembler::cmpeq(const PRegisterWithLaneSize& pd,
2813
const PRegisterZ& pg,
2814
const ZRegister& zn,
2815
int imm5) {
2816
// CMPEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2817
// 0010 0101 ..0. .... 100. .... ...0 ....
2818
// size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2819
// | ne<4> = 0 | Pd<3:0>
2820
2821
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2822
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2823
2824
CompareVectors(pd, pg, zn, imm5, CMPEQ_p_p_zi);
2825
}
2826
2827
void Assembler::cmpge(const PRegisterWithLaneSize& pd,
2828
const PRegisterZ& pg,
2829
const ZRegister& zn,
2830
int imm5) {
2831
// CMPGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2832
// 0010 0101 ..0. .... 000. .... ...0 ....
2833
// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2834
// | ne<4> = 0 | Pd<3:0>
2835
2836
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2837
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2838
2839
CompareVectors(pd, pg, zn, imm5, CMPGE_p_p_zi);
2840
}
2841
2842
void Assembler::cmpgt(const PRegisterWithLaneSize& pd,
2843
const PRegisterZ& pg,
2844
const ZRegister& zn,
2845
int imm5) {
2846
// CMPGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2847
// 0010 0101 ..0. .... 000. .... ...1 ....
2848
// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2849
// | ne<4> = 1 | Pd<3:0>
2850
2851
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2852
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2853
2854
CompareVectors(pd, pg, zn, imm5, CMPGT_p_p_zi);
2855
}
2856
2857
void Assembler::cmple(const PRegisterWithLaneSize& pd,
2858
const PRegisterZ& pg,
2859
const ZRegister& zn,
2860
int imm5) {
2861
// CMPLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2862
// 0010 0101 ..0. .... 001. .... ...1 ....
2863
// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>
2864
// | ne<4> = 1 | Pd<3:0>
2865
2866
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2867
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2868
2869
CompareVectors(pd, pg, zn, imm5, CMPLE_p_p_zi);
2870
}
2871
2872
void Assembler::cmplt(const PRegisterWithLaneSize& pd,
2873
const PRegisterZ& pg,
2874
const ZRegister& zn,
2875
int imm5) {
2876
// CMPLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2877
// 0010 0101 ..0. .... 001. .... ...0 ....
2878
// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>
2879
// | ne<4> = 0 | Pd<3:0>
2880
2881
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2882
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2883
2884
CompareVectors(pd, pg, zn, imm5, CMPLT_p_p_zi);
2885
}
2886
2887
void Assembler::cmpne(const PRegisterWithLaneSize& pd,
2888
const PRegisterZ& pg,
2889
const ZRegister& zn,
2890
int imm5) {
2891
// CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2892
// 0010 0101 ..0. .... 100. .... ...1 ....
2893
// size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>
2894
// | ne<4> = 1 | Pd<3:0>
2895
2896
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2897
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2898
2899
CompareVectors(pd, pg, zn, imm5, CMPNE_p_p_zi);
2900
}
2901
2902
// SVEIntCompareUnsignedImm.
2903
2904
void Assembler::cmphi(const PRegisterWithLaneSize& pd,
2905
const PRegisterZ& pg,
2906
const ZRegister& zn,
2907
unsigned imm7) {
2908
// CMPHI <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2909
// 0010 0100 ..1. .... ..0. .... ...1 ....
2910
// size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
2911
// Pd<3:0>
2912
2913
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2914
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2915
2916
CompareVectors(pd, pg, zn, imm7, CMPHI_p_p_zi);
2917
}
2918
2919
void Assembler::cmphs(const PRegisterWithLaneSize& pd,
2920
const PRegisterZ& pg,
2921
const ZRegister& zn,
2922
unsigned imm7) {
2923
// CMPHS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2924
// 0010 0100 ..1. .... ..0. .... ...0 ....
2925
// size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
2926
// Pd<3:0>
2927
2928
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2929
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2930
2931
CompareVectors(pd, pg, zn, imm7, CMPHS_p_p_zi);
2932
}
2933
2934
void Assembler::cmplo(const PRegisterWithLaneSize& pd,
2935
const PRegisterZ& pg,
2936
const ZRegister& zn,
2937
unsigned imm7) {
2938
// CMPLO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2939
// 0010 0100 ..1. .... ..1. .... ...0 ....
2940
// size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |
2941
// Pd<3:0>
2942
2943
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2944
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2945
2946
CompareVectors(pd, pg, zn, imm7, CMPLO_p_p_zi);
2947
}
2948
2949
void Assembler::cmpls(const PRegisterWithLaneSize& pd,
2950
const PRegisterZ& pg,
2951
const ZRegister& zn,
2952
unsigned imm7) {
2953
// CMPLS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>
2954
// 0010 0100 ..1. .... ..1. .... ...1 ....
2955
// size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |
2956
// Pd<3:0>
2957
2958
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2959
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2960
2961
CompareVectors(pd, pg, zn, imm7, CMPLS_p_p_zi);
2962
}
2963
2964
// SVEIntCompareVectors.
2965
2966
// This prototype maps to 2 instruction encodings:
2967
// CMPEQ_p_p_zw
2968
// CMPEQ_p_p_zz
2969
void Assembler::cmpeq(const PRegisterWithLaneSize& pd,
2970
const PRegisterZ& pg,
2971
const ZRegister& zn,
2972
const ZRegister& zm) {
2973
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2974
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2975
SVEIntCompareVectorsOp op = CMPEQ_p_p_zz;
2976
if (!AreSameLaneSize(zn, zm)) {
2977
VIXL_ASSERT(zm.IsLaneSizeD());
2978
op = CMPEQ_p_p_zw;
2979
}
2980
CompareVectors(pd, pg, zn, zm, op);
2981
}
2982
2983
// This prototype maps to 2 instruction encodings:
2984
// CMPGE_p_p_zw
2985
// CMPGE_p_p_zz
2986
void Assembler::cmpge(const PRegisterWithLaneSize& pd,
2987
const PRegisterZ& pg,
2988
const ZRegister& zn,
2989
const ZRegister& zm) {
2990
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
2991
VIXL_ASSERT(AreSameLaneSize(pd, zn));
2992
SVEIntCompareVectorsOp op = CMPGE_p_p_zz;
2993
if (!AreSameLaneSize(zn, zm)) {
2994
VIXL_ASSERT(zm.IsLaneSizeD());
2995
op = CMPGE_p_p_zw;
2996
}
2997
CompareVectors(pd, pg, zn, zm, op);
2998
}
2999
3000
// This prototype maps to 2 instruction encodings:
3001
// CMPGT_p_p_zw
3002
// CMPGT_p_p_zz
3003
void Assembler::cmpgt(const PRegisterWithLaneSize& pd,
3004
const PRegisterZ& pg,
3005
const ZRegister& zn,
3006
const ZRegister& zm) {
3007
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3008
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3009
SVEIntCompareVectorsOp op = CMPGT_p_p_zz;
3010
if (!AreSameLaneSize(zn, zm)) {
3011
VIXL_ASSERT(zm.IsLaneSizeD());
3012
op = CMPGT_p_p_zw;
3013
}
3014
CompareVectors(pd, pg, zn, zm, op);
3015
}
3016
3017
// This prototype maps to 2 instruction encodings:
3018
// CMPHI_p_p_zw
3019
// CMPHI_p_p_zz
3020
void Assembler::cmphi(const PRegisterWithLaneSize& pd,
3021
const PRegisterZ& pg,
3022
const ZRegister& zn,
3023
const ZRegister& zm) {
3024
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3025
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3026
SVEIntCompareVectorsOp op = CMPHI_p_p_zz;
3027
if (!AreSameLaneSize(zn, zm)) {
3028
VIXL_ASSERT(zm.IsLaneSizeD());
3029
op = CMPHI_p_p_zw;
3030
}
3031
CompareVectors(pd, pg, zn, zm, op);
3032
}
3033
3034
// This prototype maps to 2 instruction encodings:
3035
// CMPHS_p_p_zw
3036
// CMPHS_p_p_zz
3037
void Assembler::cmphs(const PRegisterWithLaneSize& pd,
3038
const PRegisterZ& pg,
3039
const ZRegister& zn,
3040
const ZRegister& zm) {
3041
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3042
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3043
SVEIntCompareVectorsOp op = CMPHS_p_p_zz;
3044
if (!AreSameLaneSize(zn, zm)) {
3045
VIXL_ASSERT(zm.IsLaneSizeD());
3046
op = CMPHS_p_p_zw;
3047
}
3048
CompareVectors(pd, pg, zn, zm, op);
3049
}
3050
3051
void Assembler::cmple(const PRegisterWithLaneSize& pd,
3052
const PRegisterZ& pg,
3053
const ZRegister& zn,
3054
const ZRegister& zm) {
3055
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3056
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3057
if (AreSameLaneSize(zn, zm)) {
3058
cmpge(pd, pg, zm, zn);
3059
return;
3060
}
3061
VIXL_ASSERT(zm.IsLaneSizeD());
3062
VIXL_ASSERT(!zn.IsLaneSizeD());
3063
3064
CompareVectors(pd, pg, zn, zm, CMPLE_p_p_zw);
3065
}
3066
3067
void Assembler::cmplo(const PRegisterWithLaneSize& pd,
3068
const PRegisterZ& pg,
3069
const ZRegister& zn,
3070
const ZRegister& zm) {
3071
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3072
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3073
if (AreSameLaneSize(zn, zm)) {
3074
cmphi(pd, pg, zm, zn);
3075
return;
3076
}
3077
VIXL_ASSERT(zm.IsLaneSizeD());
3078
VIXL_ASSERT(!zn.IsLaneSizeD());
3079
3080
CompareVectors(pd, pg, zn, zm, CMPLO_p_p_zw);
3081
}
3082
3083
void Assembler::cmpls(const PRegisterWithLaneSize& pd,
3084
const PRegisterZ& pg,
3085
const ZRegister& zn,
3086
const ZRegister& zm) {
3087
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3088
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3089
if (AreSameLaneSize(zn, zm)) {
3090
cmphs(pd, pg, zm, zn);
3091
return;
3092
}
3093
VIXL_ASSERT(zm.IsLaneSizeD());
3094
VIXL_ASSERT(!zn.IsLaneSizeD());
3095
3096
CompareVectors(pd, pg, zn, zm, CMPLS_p_p_zw);
3097
}
3098
3099
void Assembler::cmplt(const PRegisterWithLaneSize& pd,
3100
const PRegisterZ& pg,
3101
const ZRegister& zn,
3102
const ZRegister& zm) {
3103
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3104
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3105
if (AreSameLaneSize(zn, zm)) {
3106
cmpgt(pd, pg, zm, zn);
3107
return;
3108
}
3109
VIXL_ASSERT(zm.IsLaneSizeD());
3110
VIXL_ASSERT(!zn.IsLaneSizeD());
3111
3112
CompareVectors(pd, pg, zn, zm, CMPLT_p_p_zw);
3113
}
3114
3115
// This prototype maps to 2 instruction encodings:
3116
// CMPNE_p_p_zw
3117
// CMPNE_p_p_zz
3118
void Assembler::cmpne(const PRegisterWithLaneSize& pd,
3119
const PRegisterZ& pg,
3120
const ZRegister& zn,
3121
const ZRegister& zm) {
3122
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3123
VIXL_ASSERT(AreSameLaneSize(pd, zn));
3124
SVEIntCompareVectorsOp op = CMPNE_p_p_zz;
3125
if (!AreSameLaneSize(zn, zm)) {
3126
VIXL_ASSERT(zm.IsLaneSizeD());
3127
op = CMPNE_p_p_zw;
3128
}
3129
CompareVectors(pd, pg, zn, zm, op);
3130
}
3131
3132
// SVEIntMiscUnpredicated.
3133
3134
void Assembler::fexpa(const ZRegister& zd, const ZRegister& zn) {
3135
// FEXPA <Zd>.<T>, <Zn>.<T>
3136
// 0000 0100 ..10 0000 1011 10.. .... ....
3137
// size<23:22> | opc<20:16> = 00000 | Zn<9:5> | Zd<4:0>
3138
3139
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3140
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3141
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3142
3143
Emit(FEXPA_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
3144
}
3145
3146
void Assembler::ftssel(const ZRegister& zd,
3147
const ZRegister& zn,
3148
const ZRegister& zm) {
3149
// FTSSEL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
3150
// 0000 0100 ..1. .... 1011 00.. .... ....
3151
// size<23:22> | Zm<20:16> | op<10> = 0 | Zn<9:5> | Zd<4:0>
3152
3153
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3154
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
3155
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3156
3157
Emit(FTSSEL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
3158
}
3159
3160
void Assembler::movprfx(const ZRegister& zd, const ZRegister& zn) {
3161
// MOVPRFX <Zd>, <Zn>
3162
// 0000 0100 0010 0000 1011 11.. .... ....
3163
// opc<23:22> = 00 | opc2<20:16> = 00000 | Zn<9:5> | Zd<4:0>
3164
3165
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3166
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3167
3168
Emit(MOVPRFX_z_z | Rd(zd) | Rn(zn));
3169
}
3170
3171
// SVEIntMulAddPredicated.
3172
3173
void Assembler::mad(const ZRegister& zdn,
3174
const PRegisterM& pg,
3175
const ZRegister& zm,
3176
const ZRegister& za) {
3177
// MAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
3178
// 0000 0100 ..0. .... 110. .... .... ....
3179
// size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Za<9:5> | Zdn<4:0>
3180
3181
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3182
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
3183
3184
Emit(MAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));
3185
}
3186
3187
void Assembler::mla(const ZRegister& zda,
3188
const PRegisterM& pg,
3189
const ZRegister& zn,
3190
const ZRegister& zm) {
3191
// MLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
3192
// 0000 0100 ..0. .... 010. .... .... ....
3193
// size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Zn<9:5> | Zda<4:0>
3194
3195
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3196
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
3197
3198
Emit(MLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
3199
}
3200
3201
void Assembler::mls(const ZRegister& zda,
3202
const PRegisterM& pg,
3203
const ZRegister& zn,
3204
const ZRegister& zm) {
3205
// MLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>
3206
// 0000 0100 ..0. .... 011. .... .... ....
3207
// size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Zn<9:5> | Zda<4:0>
3208
3209
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3210
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
3211
3212
Emit(MLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));
3213
}
3214
3215
void Assembler::msb(const ZRegister& zdn,
3216
const PRegisterM& pg,
3217
const ZRegister& zm,
3218
const ZRegister& za) {
3219
// MSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>
3220
// 0000 0100 ..0. .... 111. .... .... ....
3221
// size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Za<9:5> | Zdn<4:0>
3222
3223
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3224
VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));
3225
3226
Emit(MSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));
3227
}
3228
3229
// SVEIntMulAddUnpredicated.
3230
3231
void Assembler::sdot(const ZRegister& zda,
3232
const ZRegister& zn,
3233
const ZRegister& zm) {
3234
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3235
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
3236
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
3237
VIXL_ASSERT(AreSameLaneSize(zm, zn));
3238
3239
Emit(SDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
3240
}
3241
3242
void Assembler::udot(const ZRegister& zda,
3243
const ZRegister& zn,
3244
const ZRegister& zm) {
3245
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3246
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
3247
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
3248
VIXL_ASSERT(AreSameLaneSize(zm, zn));
3249
3250
Emit(UDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
3251
}
3252
3253
// SVEIntReduction.
3254
3255
void Assembler::andv(const VRegister& vd,
3256
const PRegister& pg,
3257
const ZRegister& zn) {
3258
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3259
VIXL_ASSERT(vd.IsScalar());
3260
3261
Emit(ANDV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3262
}
3263
3264
void Assembler::eorv(const VRegister& vd,
3265
const PRegister& pg,
3266
const ZRegister& zn) {
3267
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3268
VIXL_ASSERT(vd.IsScalar());
3269
3270
Emit(EORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3271
}
3272
3273
void Assembler::movprfx(const ZRegister& zd,
3274
const PRegister& pg,
3275
const ZRegister& zn) {
3276
// MOVPRFX <Zd>.<T>, <Pg>/<ZM>, <Zn>.<T>
3277
// 0000 0100 ..01 000. 001. .... .... ....
3278
// size<23:22> | opc<18:17> = 00 | M<16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
3279
3280
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3281
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3282
VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
3283
VIXL_ASSERT(!pg.HasLaneSize());
3284
3285
Instr m = pg.IsMerging() ? 0x00010000 : 0x00000000;
3286
Emit(MOVPRFX_z_p_z | SVESize(zd) | m | Rd(zd) | PgLow8(pg) | Rn(zn));
3287
}
3288
3289
void Assembler::orv(const VRegister& vd,
3290
const PRegister& pg,
3291
const ZRegister& zn) {
3292
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3293
VIXL_ASSERT(vd.IsScalar());
3294
3295
Emit(ORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3296
}
3297
3298
void Assembler::saddv(const VRegister& dd,
3299
const PRegister& pg,
3300
const ZRegister& zn) {
3301
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3302
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kDRegSizeInBytes);
3303
3304
Emit(SADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));
3305
}
3306
3307
void Assembler::smaxv(const VRegister& vd,
3308
const PRegister& pg,
3309
const ZRegister& zn) {
3310
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3311
VIXL_ASSERT(vd.IsScalar());
3312
3313
Emit(SMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3314
}
3315
3316
void Assembler::sminv(const VRegister& vd,
3317
const PRegister& pg,
3318
const ZRegister& zn) {
3319
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3320
VIXL_ASSERT(vd.IsScalar());
3321
3322
Emit(SMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3323
}
3324
3325
void Assembler::uaddv(const VRegister& dd,
3326
const PRegister& pg,
3327
const ZRegister& zn) {
3328
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3329
3330
Emit(UADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));
3331
}
3332
3333
void Assembler::umaxv(const VRegister& vd,
3334
const PRegister& pg,
3335
const ZRegister& zn) {
3336
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3337
VIXL_ASSERT(vd.IsScalar());
3338
3339
Emit(UMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3340
}
3341
3342
void Assembler::uminv(const VRegister& vd,
3343
const PRegister& pg,
3344
const ZRegister& zn) {
3345
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3346
VIXL_ASSERT(vd.IsScalar());
3347
3348
Emit(UMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
3349
}
3350
3351
// SVEIntUnaryArithmeticPredicated.
3352
3353
void Assembler::abs(const ZRegister& zd,
3354
const PRegisterM& pg,
3355
const ZRegister& zn) {
3356
// ABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3357
// 0000 0100 ..01 0110 101. .... .... ....
3358
// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3359
3360
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3361
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3362
3363
Emit(ABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3364
}
3365
3366
void Assembler::cls(const ZRegister& zd,
3367
const PRegisterM& pg,
3368
const ZRegister& zn) {
3369
// CLS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3370
// 0000 0100 ..01 1000 101. .... .... ....
3371
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3372
3373
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3374
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3375
3376
Emit(CLS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3377
}
3378
3379
void Assembler::clz(const ZRegister& zd,
3380
const PRegisterM& pg,
3381
const ZRegister& zn) {
3382
// CLZ <Zd>.<T>, <Pg>/M, <Zn>.<T>
3383
// 0000 0100 ..01 1001 101. .... .... ....
3384
// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3385
3386
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3387
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3388
3389
Emit(CLZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3390
}
3391
3392
void Assembler::cnot(const ZRegister& zd,
3393
const PRegisterM& pg,
3394
const ZRegister& zn) {
3395
// CNOT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3396
// 0000 0100 ..01 1011 101. .... .... ....
3397
// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3398
3399
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3400
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3401
3402
Emit(CNOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3403
}
3404
3405
void Assembler::cnt(const ZRegister& zd,
3406
const PRegisterM& pg,
3407
const ZRegister& zn) {
3408
// CNT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3409
// 0000 0100 ..01 1010 101. .... .... ....
3410
// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3411
3412
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3413
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3414
3415
Emit(CNT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3416
}
3417
3418
void Assembler::fabs(const ZRegister& zd,
3419
const PRegisterM& pg,
3420
const ZRegister& zn) {
3421
// FABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
3422
// 0000 0100 ..01 1100 101. .... .... ....
3423
// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3424
3425
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3426
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3427
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3428
3429
Emit(FABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3430
}
3431
3432
void Assembler::fneg(const ZRegister& zd,
3433
const PRegisterM& pg,
3434
const ZRegister& zn) {
3435
// FNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
3436
// 0000 0100 ..01 1101 101. .... .... ....
3437
// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3438
3439
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3440
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3441
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3442
3443
Emit(FNEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3444
}
3445
3446
void Assembler::neg(const ZRegister& zd,
3447
const PRegisterM& pg,
3448
const ZRegister& zn) {
3449
// NEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
3450
// 0000 0100 ..01 0111 101. .... .... ....
3451
// size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3452
3453
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3454
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3455
3456
Emit(NEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3457
}
3458
3459
void Assembler::not_(const ZRegister& zd,
3460
const PRegisterM& pg,
3461
const ZRegister& zn) {
3462
// NOT <Zd>.<T>, <Pg>/M, <Zn>.<T>
3463
// 0000 0100 ..01 1110 101. .... .... ....
3464
// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3465
3466
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3467
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3468
3469
Emit(NOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3470
}
3471
3472
void Assembler::sxtb(const ZRegister& zd,
3473
const PRegisterM& pg,
3474
const ZRegister& zn) {
3475
// SXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>
3476
// 0000 0100 ..01 0000 101. .... .... ....
3477
// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3478
3479
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3480
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3481
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);
3482
3483
Emit(SXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3484
}
3485
3486
void Assembler::sxth(const ZRegister& zd,
3487
const PRegisterM& pg,
3488
const ZRegister& zn) {
3489
// SXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>
3490
// 0000 0100 ..01 0010 101. .... .... ....
3491
// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3492
3493
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3494
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3495
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);
3496
3497
Emit(SXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3498
}
3499
3500
void Assembler::sxtw(const ZRegister& zd,
3501
const PRegisterM& pg,
3502
const ZRegister& zn) {
3503
// SXTW <Zd>.D, <Pg>/M, <Zn>.D
3504
// 0000 0100 ..01 0100 101. .... .... ....
3505
// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3506
3507
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3508
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3509
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);
3510
3511
Emit(SXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3512
}
3513
3514
void Assembler::uxtb(const ZRegister& zd,
3515
const PRegisterM& pg,
3516
const ZRegister& zn) {
3517
// UXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>
3518
// 0000 0100 ..01 0001 101. .... .... ....
3519
// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3520
3521
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3522
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3523
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);
3524
3525
Emit(UXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3526
}
3527
3528
void Assembler::uxth(const ZRegister& zd,
3529
const PRegisterM& pg,
3530
const ZRegister& zn) {
3531
// UXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>
3532
// 0000 0100 ..01 0011 101. .... .... ....
3533
// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3534
3535
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3536
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3537
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);
3538
3539
Emit(UXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3540
}
3541
3542
void Assembler::uxtw(const ZRegister& zd,
3543
const PRegisterM& pg,
3544
const ZRegister& zn) {
3545
// UXTW <Zd>.D, <Pg>/M, <Zn>.D
3546
// 0000 0100 ..01 0101 101. .... .... ....
3547
// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>
3548
3549
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3550
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3551
VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);
3552
3553
Emit(UXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
3554
}
3555
3556
// SVEIntWideImmPredicated.
3557
3558
void Assembler::cpy(const ZRegister& zd,
3559
const PRegister& pg,
3560
int imm8,
3561
int shift) {
3562
// CPY <Zd>.<T>, <Pg>/<ZM>, #<imm>{, <shift>}
3563
// 0000 0101 ..01 .... 0... .... .... ....
3564
// size<23:22> | Pg<19:16> | M<14> | sh<13> | imm8<12:5> | Zd<4:0>
3565
3566
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3567
VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
3568
3569
ResolveSVEImm8Shift(&imm8, &shift);
3570
3571
Instr sh = (shift > 0) ? (1 << 13) : 0;
3572
Instr m = pg.IsMerging() ? (1 << 14) : 0;
3573
Emit(CPY_z_p_i | m | sh | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) |
3574
ImmField<12, 5>(imm8));
3575
}
3576
3577
void Assembler::fcpy(const ZRegister& zd, const PRegisterM& pg, double imm) {
3578
// FCPY <Zd>.<T>, <Pg>/M, #<const>
3579
// 0000 0101 ..01 .... 110. .... .... ....
3580
// size<23:22> | Pg<19:16> | imm8<12:5> | Zd<4:0>
3581
3582
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3583
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3584
3585
Instr imm_field = ImmUnsignedField<12, 5>(FP64ToImm8(imm));
3586
Emit(FCPY_z_p_i | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) | imm_field);
3587
}
3588
3589
// SVEIntAddSubtractImmUnpredicated.
3590
3591
void Assembler::SVEIntAddSubtractImmUnpredicatedHelper(
3592
SVEIntAddSubtractImm_UnpredicatedOp op,
3593
const ZRegister& zd,
3594
int imm8,
3595
int shift) {
3596
if (shift < 0) {
3597
VIXL_ASSERT(shift == -1);
3598
// Derive the shift amount from the immediate.
3599
if (IsUint8(imm8)) {
3600
shift = 0;
3601
} else if (IsUint16(imm8) && ((imm8 % 256) == 0)) {
3602
imm8 /= 256;
3603
shift = 8;
3604
}
3605
}
3606
3607
VIXL_ASSERT(IsUint8(imm8));
3608
VIXL_ASSERT((shift == 0) || (shift == 8));
3609
3610
Instr shift_bit = (shift > 0) ? (1 << 13) : 0;
3611
Emit(op | SVESize(zd) | Rd(zd) | shift_bit | ImmUnsignedField<12, 5>(imm8));
3612
}
3613
3614
void Assembler::add(const ZRegister& zd,
3615
const ZRegister& zn,
3616
int imm8,
3617
int shift) {
3618
// ADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3619
// 0010 0101 ..10 0000 11.. .... .... ....
3620
// size<23:22> | opc<18:16> = 000 | sh<13> | imm8<12:5> | Zdn<4:0>
3621
3622
USE(zn);
3623
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3624
VIXL_ASSERT(zd.Is(zn));
3625
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3626
3627
SVEIntAddSubtractImmUnpredicatedHelper(ADD_z_zi, zd, imm8, shift);
3628
}
3629
3630
void Assembler::dup(const ZRegister& zd, int imm8, int shift) {
3631
// DUP <Zd>.<T>, #<imm>{, <shift>}
3632
// 0010 0101 ..11 1000 11.. .... .... ....
3633
// size<23:22> | opc<18:17> = 00 | sh<13> | imm8<12:5> | Zd<4:0>
3634
3635
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3636
3637
ResolveSVEImm8Shift(&imm8, &shift);
3638
VIXL_ASSERT((shift < 8) || !zd.IsLaneSizeB());
3639
3640
Instr shift_bit = (shift > 0) ? (1 << 13) : 0;
3641
Emit(DUP_z_i | SVESize(zd) | Rd(zd) | shift_bit | ImmField<12, 5>(imm8));
3642
}
3643
3644
void Assembler::fdup(const ZRegister& zd, double imm) {
3645
// FDUP <Zd>.<T>, #<const>
3646
// 0010 0101 ..11 1001 110. .... .... ....
3647
// size<23:22> | opc<18:17> = 00 | o2<13> = 0 | imm8<12:5> | Zd<4:0>
3648
3649
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3650
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
3651
3652
Instr encoded_imm = FP64ToImm8(imm) << 5;
3653
Emit(FDUP_z_i | SVESize(zd) | encoded_imm | Rd(zd));
3654
}
3655
3656
void Assembler::mul(const ZRegister& zd, const ZRegister& zn, int imm8) {
3657
// MUL <Zdn>.<T>, <Zdn>.<T>, #<imm>
3658
// 0010 0101 ..11 0000 110. .... .... ....
3659
// size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3660
3661
USE(zn);
3662
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3663
VIXL_ASSERT(zd.Is(zn));
3664
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3665
3666
Emit(MUL_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3667
}
3668
3669
void Assembler::smax(const ZRegister& zd, const ZRegister& zn, int imm8) {
3670
// SMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>
3671
// 0010 0101 ..10 1000 110. .... .... ....
3672
// size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3673
3674
USE(zn);
3675
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3676
VIXL_ASSERT(zd.Is(zn));
3677
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3678
3679
Emit(SMAX_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3680
}
3681
3682
void Assembler::smin(const ZRegister& zd, const ZRegister& zn, int imm8) {
3683
// SMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>
3684
// 0010 0101 ..10 1010 110. .... .... ....
3685
// size<23:22> | opc<18:16> = 010 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3686
3687
USE(zn);
3688
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3689
VIXL_ASSERT(zd.Is(zn));
3690
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3691
3692
Emit(SMIN_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));
3693
}
3694
3695
void Assembler::sqadd(const ZRegister& zd,
3696
const ZRegister& zn,
3697
int imm8,
3698
int shift) {
3699
// SQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3700
// 0010 0101 ..10 0100 11.. .... .... ....
3701
// size<23:22> | opc<18:16> = 100 | sh<13> | imm8<12:5> | Zdn<4:0>
3702
3703
USE(zn);
3704
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3705
VIXL_ASSERT(zd.Is(zn));
3706
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3707
3708
SVEIntAddSubtractImmUnpredicatedHelper(SQADD_z_zi, zd, imm8, shift);
3709
}
3710
3711
void Assembler::sqsub(const ZRegister& zd,
3712
const ZRegister& zn,
3713
int imm8,
3714
int shift) {
3715
// SQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3716
// 0010 0101 ..10 0110 11.. .... .... ....
3717
// size<23:22> | opc<18:16> = 110 | sh<13> | imm8<12:5> | Zdn<4:0>
3718
3719
USE(zn);
3720
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3721
VIXL_ASSERT(zd.Is(zn));
3722
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3723
3724
SVEIntAddSubtractImmUnpredicatedHelper(SQSUB_z_zi, zd, imm8, shift);
3725
}
3726
3727
void Assembler::sub(const ZRegister& zd,
3728
const ZRegister& zn,
3729
int imm8,
3730
int shift) {
3731
// SUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3732
// 0010 0101 ..10 0001 11.. .... .... ....
3733
// size<23:22> | opc<18:16> = 001 | sh<13> | imm8<12:5> | Zdn<4:0>
3734
3735
USE(zn);
3736
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3737
VIXL_ASSERT(zd.Is(zn));
3738
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3739
3740
SVEIntAddSubtractImmUnpredicatedHelper(SUB_z_zi, zd, imm8, shift);
3741
}
3742
3743
void Assembler::subr(const ZRegister& zd,
3744
const ZRegister& zn,
3745
int imm8,
3746
int shift) {
3747
// SUBR <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3748
// 0010 0101 ..10 0011 11.. .... .... ....
3749
// size<23:22> | opc<18:16> = 011 | sh<13> | imm8<12:5> | Zdn<4:0>
3750
3751
USE(zn);
3752
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3753
VIXL_ASSERT(zd.Is(zn));
3754
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3755
3756
SVEIntAddSubtractImmUnpredicatedHelper(SUBR_z_zi, zd, imm8, shift);
3757
}
3758
3759
void Assembler::umax(const ZRegister& zd, const ZRegister& zn, int imm8) {
3760
// UMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>
3761
// 0010 0101 ..10 1001 110. .... .... ....
3762
// size<23:22> | opc<18:16> = 001 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3763
3764
USE(zn);
3765
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3766
VIXL_ASSERT(zd.Is(zn));
3767
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3768
3769
Emit(UMAX_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));
3770
}
3771
3772
void Assembler::umin(const ZRegister& zd, const ZRegister& zn, int imm8) {
3773
// UMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>
3774
// 0010 0101 ..10 1011 110. .... .... ....
3775
// size<23:22> | opc<18:16> = 011 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>
3776
3777
USE(zn);
3778
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3779
VIXL_ASSERT(zd.Is(zn));
3780
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3781
3782
Emit(UMIN_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));
3783
}
3784
3785
void Assembler::uqadd(const ZRegister& zd,
3786
const ZRegister& zn,
3787
int imm8,
3788
int shift) {
3789
// UQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3790
// 0010 0101 ..10 0101 11.. .... .... ....
3791
// size<23:22> | opc<18:16> = 101 | sh<13> | imm8<12:5> | Zdn<4:0>
3792
3793
USE(zn);
3794
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3795
VIXL_ASSERT(zd.Is(zn));
3796
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3797
3798
SVEIntAddSubtractImmUnpredicatedHelper(UQADD_z_zi, zd, imm8, shift);
3799
}
3800
3801
void Assembler::uqsub(const ZRegister& zd,
3802
const ZRegister& zn,
3803
int imm8,
3804
int shift) {
3805
// UQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}
3806
// 0010 0101 ..10 0111 11.. .... .... ....
3807
// size<23:22> | opc<18:16> = 111 | sh<13> | imm8<12:5> | Zdn<4:0>
3808
3809
USE(zn);
3810
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
3811
VIXL_ASSERT(zd.Is(zn));
3812
VIXL_ASSERT(AreSameLaneSize(zd, zn));
3813
3814
SVEIntAddSubtractImmUnpredicatedHelper(UQSUB_z_zi, zd, imm8, shift);
3815
}
3816
3817
// SVEMemLoad.
3818
3819
void Assembler::SVELdSt1Helper(unsigned msize_in_bytes_log2,
3820
const ZRegister& zt,
3821
const PRegister& pg,
3822
const SVEMemOperand& addr,
3823
bool is_signed,
3824
Instr op) {
3825
VIXL_ASSERT(addr.IsContiguous());
3826
3827
Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr);
3828
Instr dtype =
3829
SVEDtype(msize_in_bytes_log2, zt.GetLaneSizeInBytesLog2(), is_signed);
3830
Emit(op | mem_op | dtype | Rt(zt) | PgLow8(pg));
3831
}
3832
3833
void Assembler::SVELdSt234Helper(int num_regs,
3834
const ZRegister& zt1,
3835
const PRegister& pg,
3836
const SVEMemOperand& addr,
3837
Instr op) {
3838
VIXL_ASSERT((num_regs >= 2) && (num_regs <= 4));
3839
3840
unsigned msize_in_bytes_log2 = zt1.GetLaneSizeInBytesLog2();
3841
Instr num = (num_regs - 1) << 21;
3842
Instr msz = msize_in_bytes_log2 << 23;
3843
Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, num_regs, addr);
3844
Emit(op | mem_op | msz | num | Rt(zt1) | PgLow8(pg));
3845
}
3846
3847
void Assembler::SVELd1Helper(unsigned msize_in_bytes_log2,
3848
const ZRegister& zt,
3849
const PRegisterZ& pg,
3850
const SVEMemOperand& addr,
3851
bool is_signed) {
3852
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
3853
if (is_signed) {
3854
// Sign-extension is only possible when the vector elements are larger than
3855
// the elements in memory.
3856
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
3857
}
3858
3859
if (addr.IsScatterGather()) {
3860
bool is_load = true;
3861
bool is_ff = false;
3862
SVEScatterGatherHelper(msize_in_bytes_log2,
3863
zt,
3864
pg,
3865
addr,
3866
is_load,
3867
is_signed,
3868
is_ff);
3869
return;
3870
}
3871
3872
Instr op = 0xffffffff;
3873
if (addr.IsScalarPlusImmediate()) {
3874
op = SVEContiguousLoad_ScalarPlusImmFixed;
3875
} else if (addr.IsScalarPlusScalar()) {
3876
// Rm must not be xzr.
3877
VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
3878
op = SVEContiguousLoad_ScalarPlusScalarFixed;
3879
} else {
3880
VIXL_UNIMPLEMENTED();
3881
}
3882
SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);
3883
}
3884
3885
void Assembler::SVELdff1Helper(unsigned msize_in_bytes_log2,
3886
const ZRegister& zt,
3887
const PRegisterZ& pg,
3888
const SVEMemOperand& addr,
3889
bool is_signed) {
3890
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
3891
if (is_signed) {
3892
// Sign-extension is only possible when the vector elements are larger than
3893
// the elements in memory.
3894
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
3895
}
3896
3897
if (addr.IsScatterGather()) {
3898
bool is_load = true;
3899
bool is_ff = true;
3900
SVEScatterGatherHelper(msize_in_bytes_log2,
3901
zt,
3902
pg,
3903
addr,
3904
is_load,
3905
is_signed,
3906
is_ff);
3907
return;
3908
}
3909
3910
if (addr.IsPlainScalar()) {
3911
// SVEMemOperand(x0) is treated as a scalar-plus-immediate form ([x0, #0]).
3912
// In these instructions, we want to treat it as [x0, xzr].
3913
SVEMemOperand addr_scalar_plus_scalar(addr.GetScalarBase(), xzr);
3914
// Guard against infinite recursion.
3915
VIXL_ASSERT(!addr_scalar_plus_scalar.IsPlainScalar());
3916
SVELdff1Helper(msize_in_bytes_log2,
3917
zt,
3918
pg,
3919
addr_scalar_plus_scalar,
3920
is_signed);
3921
return;
3922
}
3923
3924
Instr op = 0xffffffff;
3925
if (addr.IsScalarPlusScalar()) {
3926
op = SVEContiguousFirstFaultLoad_ScalarPlusScalarFixed;
3927
} else {
3928
VIXL_UNIMPLEMENTED();
3929
}
3930
SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);
3931
}
3932
3933
void Assembler::SVEScatterGatherHelper(unsigned msize_in_bytes_log2,
3934
const ZRegister& zt,
3935
const PRegister& pg,
3936
const SVEMemOperand& addr,
3937
bool is_load,
3938
bool is_signed,
3939
bool is_first_fault) {
3940
VIXL_ASSERT(addr.IsScatterGather());
3941
VIXL_ASSERT(zt.IsLaneSizeS() || zt.IsLaneSizeD());
3942
VIXL_ASSERT(is_load || !is_first_fault);
3943
VIXL_ASSERT(is_load || !is_signed);
3944
3945
Instr op = 0xffffffff;
3946
if (addr.IsVectorPlusImmediate()) {
3947
VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorBase()));
3948
if (is_load) {
3949
if (zt.IsLaneSizeS()) {
3950
op = SVE32BitGatherLoad_VectorPlusImmFixed;
3951
} else {
3952
op = SVE64BitGatherLoad_VectorPlusImmFixed;
3953
}
3954
} else {
3955
if (zt.IsLaneSizeS()) {
3956
op = SVE32BitScatterStore_VectorPlusImmFixed;
3957
} else {
3958
op = SVE64BitScatterStore_VectorPlusImmFixed;
3959
}
3960
}
3961
} else {
3962
VIXL_ASSERT(addr.IsScalarPlusVector());
3963
VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorOffset()));
3964
SVEOffsetModifier mod = addr.GetOffsetModifier();
3965
if (zt.IsLaneSizeS()) {
3966
VIXL_ASSERT((mod == SVE_UXTW) || (mod == SVE_SXTW));
3967
unsigned shift_amount = addr.GetShiftAmount();
3968
if (shift_amount == 0) {
3969
if (is_load) {
3970
op = SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFixed;
3971
} else {
3972
op = SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFixed;
3973
}
3974
} else if (shift_amount == 1) {
3975
VIXL_ASSERT(msize_in_bytes_log2 == kHRegSizeInBytesLog2);
3976
if (is_load) {
3977
op = SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFixed;
3978
} else {
3979
op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;
3980
}
3981
} else {
3982
VIXL_ASSERT(shift_amount == 2);
3983
VIXL_ASSERT(msize_in_bytes_log2 == kSRegSizeInBytesLog2);
3984
if (is_load) {
3985
op = SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFixed;
3986
} else {
3987
op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;
3988
}
3989
}
3990
} else if (zt.IsLaneSizeD()) {
3991
switch (mod) {
3992
case NO_SVE_OFFSET_MODIFIER:
3993
if (is_load) {
3994
op = SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFixed;
3995
} else {
3996
op = SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFixed;
3997
}
3998
break;
3999
case SVE_LSL:
4000
if (is_load) {
4001
op = SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFixed;
4002
} else {
4003
op = SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFixed;
4004
}
4005
break;
4006
case SVE_UXTW:
4007
case SVE_SXTW: {
4008
unsigned shift_amount = addr.GetShiftAmount();
4009
if (shift_amount == 0) {
4010
if (is_load) {
4011
op =
4012
SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;
4013
} else {
4014
op =
4015
SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;
4016
}
4017
} else {
4018
VIXL_ASSERT(shift_amount == msize_in_bytes_log2);
4019
if (is_load) {
4020
op = SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFixed;
4021
} else {
4022
op =
4023
SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFixed;
4024
}
4025
}
4026
break;
4027
}
4028
default:
4029
VIXL_UNIMPLEMENTED();
4030
}
4031
}
4032
}
4033
4034
Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr, is_load);
4035
Instr msz = ImmUnsignedField<24, 23>(msize_in_bytes_log2);
4036
Instr u = (!is_load || is_signed) ? 0 : (1 << 14);
4037
Instr ff = is_first_fault ? (1 << 13) : 0;
4038
Emit(op | mem_op | msz | u | ff | Rt(zt) | PgLow8(pg));
4039
}
4040
4041
void Assembler::SVELd234Helper(int num_regs,
4042
const ZRegister& zt1,
4043
const PRegisterZ& pg,
4044
const SVEMemOperand& addr) {
4045
if (addr.IsScalarPlusScalar()) {
4046
// Rm must not be xzr.
4047
VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
4048
}
4049
4050
Instr op;
4051
if (addr.IsScalarPlusImmediate()) {
4052
op = SVELoadMultipleStructures_ScalarPlusImmFixed;
4053
} else if (addr.IsScalarPlusScalar()) {
4054
op = SVELoadMultipleStructures_ScalarPlusScalarFixed;
4055
} else {
4056
// These instructions don't support any other addressing modes.
4057
VIXL_ABORT();
4058
}
4059
SVELdSt234Helper(num_regs, zt1, pg, addr, op);
4060
}
4061
4062
// SVEMemContiguousLoad.
4063
4064
#define VIXL_DEFINE_LD1(MSZ, LANE_SIZE) \
4065
void Assembler::ld1##MSZ(const ZRegister& zt, \
4066
const PRegisterZ& pg, \
4067
const SVEMemOperand& addr) { \
4068
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4069
SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \
4070
}
4071
#define VIXL_DEFINE_LD2(MSZ, LANE_SIZE) \
4072
void Assembler::ld2##MSZ(const ZRegister& zt1, \
4073
const ZRegister& zt2, \
4074
const PRegisterZ& pg, \
4075
const SVEMemOperand& addr) { \
4076
USE(zt2); \
4077
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4078
VIXL_ASSERT(AreConsecutive(zt1, zt2)); \
4079
VIXL_ASSERT(AreSameFormat(zt1, zt2)); \
4080
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
4081
SVELd234Helper(2, zt1, pg, addr); \
4082
}
4083
#define VIXL_DEFINE_LD3(MSZ, LANE_SIZE) \
4084
void Assembler::ld3##MSZ(const ZRegister& zt1, \
4085
const ZRegister& zt2, \
4086
const ZRegister& zt3, \
4087
const PRegisterZ& pg, \
4088
const SVEMemOperand& addr) { \
4089
USE(zt2, zt3); \
4090
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4091
VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3)); \
4092
VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3)); \
4093
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
4094
SVELd234Helper(3, zt1, pg, addr); \
4095
}
4096
#define VIXL_DEFINE_LD4(MSZ, LANE_SIZE) \
4097
void Assembler::ld4##MSZ(const ZRegister& zt1, \
4098
const ZRegister& zt2, \
4099
const ZRegister& zt3, \
4100
const ZRegister& zt4, \
4101
const PRegisterZ& pg, \
4102
const SVEMemOperand& addr) { \
4103
USE(zt2, zt3, zt4); \
4104
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4105
VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4)); \
4106
VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4)); \
4107
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
4108
SVELd234Helper(4, zt1, pg, addr); \
4109
}
4110
4111
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD1)
4112
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD2)
4113
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD3)
4114
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD4)
4115
4116
#define VIXL_DEFINE_LD1S(MSZ, LANE_SIZE) \
4117
void Assembler::ld1s##MSZ(const ZRegister& zt, \
4118
const PRegisterZ& pg, \
4119
const SVEMemOperand& addr) { \
4120
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4121
SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \
4122
}
4123
VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LD1S)
4124
4125
// SVEMem32BitGatherAndUnsizedContiguous.
4126
4127
void Assembler::SVELd1BroadcastHelper(unsigned msize_in_bytes_log2,
4128
const ZRegister& zt,
4129
const PRegisterZ& pg,
4130
const SVEMemOperand& addr,
4131
bool is_signed) {
4132
VIXL_ASSERT(addr.IsScalarPlusImmediate());
4133
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);
4134
if (is_signed) {
4135
// Sign-extension is only possible when the vector elements are larger than
4136
// the elements in memory.
4137
VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);
4138
}
4139
4140
int64_t imm = addr.GetImmediateOffset();
4141
int divisor = 1 << msize_in_bytes_log2;
4142
VIXL_ASSERT(imm % divisor == 0);
4143
Instr dtype = SVEDtypeSplit(msize_in_bytes_log2,
4144
zt.GetLaneSizeInBytesLog2(),
4145
is_signed);
4146
4147
Emit(SVELoadAndBroadcastElementFixed | dtype | RnSP(addr.GetScalarBase()) |
4148
ImmUnsignedField<21, 16>(imm / divisor) | Rt(zt) | PgLow8(pg));
4149
}
4150
4151
// This prototype maps to 4 instruction encodings:
4152
// LD1RB_z_p_bi_u16
4153
// LD1RB_z_p_bi_u32
4154
// LD1RB_z_p_bi_u64
4155
// LD1RB_z_p_bi_u8
4156
void Assembler::ld1rb(const ZRegister& zt,
4157
const PRegisterZ& pg,
4158
const SVEMemOperand& addr) {
4159
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4160
4161
SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, false);
4162
}
4163
4164
// This prototype maps to 3 instruction encodings:
4165
// LD1RH_z_p_bi_u16
4166
// LD1RH_z_p_bi_u32
4167
// LD1RH_z_p_bi_u64
4168
void Assembler::ld1rh(const ZRegister& zt,
4169
const PRegisterZ& pg,
4170
const SVEMemOperand& addr) {
4171
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4172
4173
SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, false);
4174
}
4175
4176
// This prototype maps to 2 instruction encodings:
4177
// LD1RW_z_p_bi_u32
4178
// LD1RW_z_p_bi_u64
4179
void Assembler::ld1rw(const ZRegister& zt,
4180
const PRegisterZ& pg,
4181
const SVEMemOperand& addr) {
4182
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4183
4184
SVELd1BroadcastHelper(kSRegSizeInBytesLog2, zt, pg, addr, false);
4185
}
4186
4187
void Assembler::ld1rd(const ZRegister& zt,
4188
const PRegisterZ& pg,
4189
const SVEMemOperand& addr) {
4190
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4191
4192
SVELd1BroadcastHelper(kDRegSizeInBytesLog2, zt, pg, addr, false);
4193
}
4194
4195
// This prototype maps to 3 instruction encodings:
4196
// LD1RSB_z_p_bi_s16
4197
// LD1RSB_z_p_bi_s32
4198
// LD1RSB_z_p_bi_s64
4199
void Assembler::ld1rsb(const ZRegister& zt,
4200
const PRegisterZ& pg,
4201
const SVEMemOperand& addr) {
4202
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4203
4204
SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, true);
4205
}
4206
4207
// This prototype maps to 2 instruction encodings:
4208
// LD1RSH_z_p_bi_s32
4209
// LD1RSH_z_p_bi_s64
4210
void Assembler::ld1rsh(const ZRegister& zt,
4211
const PRegisterZ& pg,
4212
const SVEMemOperand& addr) {
4213
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4214
4215
SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, true);
4216
}
4217
4218
void Assembler::ld1rsw(const ZRegister& zt,
4219
const PRegisterZ& pg,
4220
const SVEMemOperand& addr) {
4221
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4222
4223
SVELd1BroadcastHelper(kWRegSizeInBytesLog2, zt, pg, addr, true);
4224
}
4225
4226
void Assembler::ldr(const CPURegister& rt, const SVEMemOperand& addr) {
4227
// LDR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]
4228
4229
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4230
VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());
4231
VIXL_ASSERT(addr.IsPlainScalar() ||
4232
(addr.IsScalarPlusImmediate() &&
4233
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4234
int64_t imm9 = addr.GetImmediateOffset();
4235
VIXL_ASSERT(IsInt9(imm9));
4236
Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;
4237
Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;
4238
4239
Instr op = LDR_z_bi;
4240
if (rt.IsPRegister()) {
4241
op = LDR_p_bi;
4242
}
4243
Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);
4244
}
4245
4246
// SVEMem64BitGather.
4247
4248
// This prototype maps to 3 instruction encodings:
4249
// LDFF1B_z_p_bz_d_64_unscaled
4250
// LDFF1B_z_p_bz_d_x32_unscaled
4251
void Assembler::ldff1b(const ZRegister& zt,
4252
const PRegisterZ& pg,
4253
const Register& xn,
4254
const ZRegister& zm) {
4255
// LDFF1B { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]
4256
// 1100 0100 010. .... 111. .... .... ....
4257
// msz<24:23> = 00 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4258
// | Zt<4:0>
4259
4260
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4261
4262
Emit(LDFF1B_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4263
}
4264
4265
// This prototype maps to 2 instruction encodings:
4266
// LDFF1B_z_p_ai_d
4267
// LDFF1B_z_p_ai_s
4268
void Assembler::ldff1b(const ZRegister& zt,
4269
const PRegisterZ& pg,
4270
const ZRegister& zn,
4271
int imm5) {
4272
// LDFF1B { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4273
// 1100 0100 001. .... 111. .... .... ....
4274
// msz<24:23> = 00 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4275
// Zn<9:5> | Zt<4:0>
4276
4277
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4278
4279
Emit(LDFF1B_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4280
}
4281
4282
// This prototype maps to 4 instruction encodings:
4283
// LDFF1D_z_p_bz_d_64_scaled
4284
// LDFF1D_z_p_bz_d_64_unscaled
4285
// LDFF1D_z_p_bz_d_x32_scaled
4286
// LDFF1D_z_p_bz_d_x32_unscaled
4287
void Assembler::ldff1d(const ZRegister& zt,
4288
const PRegisterZ& pg,
4289
const Register& xn,
4290
const ZRegister& zm) {
4291
// LDFF1D { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #3]
4292
// 1100 0101 111. .... 111. .... .... ....
4293
// msz<24:23> = 11 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4294
// | Zt<4:0>
4295
4296
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4297
4298
Emit(LDFF1D_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4299
}
4300
4301
void Assembler::ldff1d(const ZRegister& zt,
4302
const PRegisterZ& pg,
4303
const ZRegister& zn,
4304
int imm5) {
4305
// LDFF1D { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4306
// 1100 0101 101. .... 111. .... .... ....
4307
// msz<24:23> = 11 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4308
// Zn<9:5> | Zt<4:0>
4309
4310
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4311
4312
Emit(LDFF1D_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4313
}
4314
4315
// This prototype maps to 6 instruction encodings:
4316
// LDFF1H_z_p_bz_d_64_scaled
4317
// LDFF1H_z_p_bz_d_64_unscaled
4318
// LDFF1H_z_p_bz_d_x32_scaled
4319
// LDFF1H_z_p_bz_d_x32_unscaled
4320
void Assembler::ldff1h(const ZRegister& zt,
4321
const PRegisterZ& pg,
4322
const Register& xn,
4323
const ZRegister& zm) {
4324
// LDFF1H { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]
4325
// 1100 0100 111. .... 111. .... .... ....
4326
// msz<24:23> = 01 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4327
// | Zt<4:0>
4328
4329
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4330
4331
Emit(LDFF1H_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4332
}
4333
4334
// This prototype maps to 2 instruction encodings:
4335
// LDFF1H_z_p_ai_d
4336
// LDFF1H_z_p_ai_s
4337
void Assembler::ldff1h(const ZRegister& zt,
4338
const PRegisterZ& pg,
4339
const ZRegister& zn,
4340
int imm5) {
4341
// LDFF1H { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4342
// 1100 0100 101. .... 111. .... .... ....
4343
// msz<24:23> = 01 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4344
// Zn<9:5> | Zt<4:0>
4345
4346
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4347
4348
Emit(LDFF1H_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4349
}
4350
4351
// This prototype maps to 3 instruction encodings:
4352
// LDFF1SB_z_p_bz_d_64_unscaled
4353
// LDFF1SB_z_p_bz_d_x32_unscaled
4354
void Assembler::ldff1sb(const ZRegister& zt,
4355
const PRegisterZ& pg,
4356
const Register& xn,
4357
const ZRegister& zm) {
4358
// LDFF1SB { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]
4359
// 1100 0100 010. .... 101. .... .... ....
4360
// msz<24:23> = 00 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4361
// | Zt<4:0>
4362
4363
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4364
4365
Emit(LDFF1SB_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4366
}
4367
4368
// This prototype maps to 2 instruction encodings:
4369
// LDFF1SB_z_p_ai_d
4370
// LDFF1SB_z_p_ai_s
4371
void Assembler::ldff1sb(const ZRegister& zt,
4372
const PRegisterZ& pg,
4373
const ZRegister& zn,
4374
int imm5) {
4375
// LDFF1SB { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4376
// 1100 0100 001. .... 101. .... .... ....
4377
// msz<24:23> = 00 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4378
// Zn<9:5> | Zt<4:0>
4379
4380
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4381
4382
Emit(LDFF1SB_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4383
ImmField<20, 16>(imm5));
4384
}
4385
4386
// This prototype maps to 6 instruction encodings:
4387
// LDFF1SH_z_p_bz_d_64_scaled
4388
// LDFF1SH_z_p_bz_d_64_unscaled
4389
// LDFF1SH_z_p_bz_d_x32_scaled
4390
// LDFF1SH_z_p_bz_d_x32_unscaled
4391
void Assembler::ldff1sh(const ZRegister& zt,
4392
const PRegisterZ& pg,
4393
const Register& xn,
4394
const ZRegister& zm) {
4395
// LDFF1SH { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]
4396
// 1100 0100 111. .... 101. .... .... ....
4397
// msz<24:23> = 01 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4398
// | Zt<4:0>
4399
4400
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4401
4402
Emit(LDFF1SH_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4403
}
4404
4405
// This prototype maps to 2 instruction encodings:
4406
// LDFF1SH_z_p_ai_d
4407
// LDFF1SH_z_p_ai_s
4408
void Assembler::ldff1sh(const ZRegister& zt,
4409
const PRegisterZ& pg,
4410
const ZRegister& zn,
4411
int imm5) {
4412
// LDFF1SH { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4413
// 1100 0100 101. .... 101. .... .... ....
4414
// msz<24:23> = 01 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4415
// Zn<9:5> | Zt<4:0>
4416
4417
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4418
4419
Emit(LDFF1SH_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4420
ImmField<20, 16>(imm5));
4421
}
4422
4423
// This prototype maps to 4 instruction encodings:
4424
// LDFF1SW_z_p_bz_d_64_scaled
4425
// LDFF1SW_z_p_bz_d_64_unscaled
4426
// LDFF1SW_z_p_bz_d_x32_scaled
4427
// LDFF1SW_z_p_bz_d_x32_unscaled
4428
void Assembler::ldff1sw(const ZRegister& zt,
4429
const PRegisterZ& pg,
4430
const Register& xn,
4431
const ZRegister& zm) {
4432
// LDFF1SW { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]
4433
// 1100 0101 011. .... 101. .... .... ....
4434
// msz<24:23> = 10 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4435
// | Zt<4:0>
4436
4437
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4438
4439
Emit(LDFF1SW_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4440
}
4441
4442
void Assembler::ldff1sw(const ZRegister& zt,
4443
const PRegisterZ& pg,
4444
const ZRegister& zn,
4445
int imm5) {
4446
// LDFF1SW { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4447
// 1100 0101 001. .... 101. .... .... ....
4448
// msz<24:23> = 10 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |
4449
// Zn<9:5> | Zt<4:0>
4450
4451
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4452
4453
Emit(LDFF1SW_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |
4454
ImmField<20, 16>(imm5));
4455
}
4456
4457
// This prototype maps to 6 instruction encodings:
4458
// LDFF1W_z_p_bz_d_64_scaled
4459
// LDFF1W_z_p_bz_d_64_unscaled
4460
// LDFF1W_z_p_bz_d_x32_scaled
4461
// LDFF1W_z_p_bz_d_x32_unscaled
4462
void Assembler::ldff1w(const ZRegister& zt,
4463
const PRegisterZ& pg,
4464
const Register& xn,
4465
const ZRegister& zm) {
4466
// LDFF1W { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]
4467
// 1100 0101 011. .... 111. .... .... ....
4468
// msz<24:23> = 10 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>
4469
// | Zt<4:0>
4470
4471
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4472
4473
Emit(LDFF1W_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));
4474
}
4475
4476
// This prototype maps to 2 instruction encodings:
4477
// LDFF1W_z_p_ai_d
4478
// LDFF1W_z_p_ai_s
4479
void Assembler::ldff1w(const ZRegister& zt,
4480
const PRegisterZ& pg,
4481
const ZRegister& zn,
4482
int imm5) {
4483
// LDFF1W { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
4484
// 1100 0101 001. .... 111. .... .... ....
4485
// msz<24:23> = 10 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |
4486
// Zn<9:5> | Zt<4:0>
4487
4488
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4489
4490
Emit(LDFF1W_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));
4491
}
4492
4493
void Assembler::SVEGatherPrefetchVectorPlusImmediateHelper(
4494
PrefetchOperation prfop,
4495
const PRegister& pg,
4496
const SVEMemOperand& addr,
4497
int prefetch_size) {
4498
VIXL_ASSERT(addr.IsVectorPlusImmediate());
4499
ZRegister zn = addr.GetVectorBase();
4500
VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4501
4502
Instr op = 0xffffffff;
4503
switch (prefetch_size) {
4504
case kBRegSize:
4505
op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_ai_s)
4506
: static_cast<Instr>(PRFB_i_p_ai_d);
4507
break;
4508
case kHRegSize:
4509
op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_ai_s)
4510
: static_cast<Instr>(PRFH_i_p_ai_d);
4511
break;
4512
case kSRegSize:
4513
op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_ai_s)
4514
: static_cast<Instr>(PRFW_i_p_ai_d);
4515
break;
4516
case kDRegSize:
4517
op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_ai_s)
4518
: static_cast<Instr>(PRFD_i_p_ai_d);
4519
break;
4520
default:
4521
VIXL_UNIMPLEMENTED();
4522
break;
4523
}
4524
4525
int64_t imm5 = addr.GetImmediateOffset();
4526
Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | Rn(zn) |
4527
ImmUnsignedField<20, 16>(imm5));
4528
}
4529
4530
void Assembler::SVEGatherPrefetchScalarPlusImmediateHelper(
4531
PrefetchOperation prfop,
4532
const PRegister& pg,
4533
const SVEMemOperand& addr,
4534
int prefetch_size) {
4535
VIXL_ASSERT(addr.IsScalarPlusImmediate());
4536
int64_t imm6 = addr.GetImmediateOffset();
4537
4538
Instr op = 0xffffffff;
4539
switch (prefetch_size) {
4540
case kBRegSize:
4541
op = PRFB_i_p_bi_s;
4542
break;
4543
case kHRegSize:
4544
op = PRFH_i_p_bi_s;
4545
break;
4546
case kSRegSize:
4547
op = PRFW_i_p_bi_s;
4548
break;
4549
case kDRegSize:
4550
op = PRFD_i_p_bi_s;
4551
break;
4552
default:
4553
VIXL_UNIMPLEMENTED();
4554
break;
4555
}
4556
4557
Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |
4558
RnSP(addr.GetScalarBase()) | ImmField<21, 16>(imm6));
4559
}
4560
4561
void Assembler::SVEContiguousPrefetchScalarPlusScalarHelper(
4562
PrefetchOperation prfop,
4563
const PRegister& pg,
4564
const SVEMemOperand& addr,
4565
int prefetch_size) {
4566
VIXL_ASSERT(addr.IsScalarPlusScalar());
4567
Instr op = 0xffffffff;
4568
4569
switch (prefetch_size) {
4570
case kBRegSize:
4571
VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);
4572
op = PRFB_i_p_br_s;
4573
break;
4574
case kHRegSize:
4575
VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4576
VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);
4577
op = PRFH_i_p_br_s;
4578
break;
4579
case kSRegSize:
4580
VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4581
VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);
4582
op = PRFW_i_p_br_s;
4583
break;
4584
case kDRegSize:
4585
VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);
4586
VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);
4587
op = PRFD_i_p_br_s;
4588
break;
4589
default:
4590
VIXL_UNIMPLEMENTED();
4591
break;
4592
}
4593
4594
VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
4595
Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |
4596
RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset()));
4597
}
4598
4599
void Assembler::SVEContiguousPrefetchScalarPlusVectorHelper(
4600
PrefetchOperation prfop,
4601
const PRegister& pg,
4602
const SVEMemOperand& addr,
4603
int prefetch_size) {
4604
VIXL_ASSERT(addr.IsScalarPlusVector());
4605
ZRegister zm = addr.GetVectorOffset();
4606
SVEOffsetModifier mod = addr.GetOffsetModifier();
4607
4608
// All prefetch scalar-plus-vector addressing modes use a shift corresponding
4609
// to the element size.
4610
switch (prefetch_size) {
4611
case kBRegSize:
4612
VIXL_ASSERT(addr.GetShiftAmount() == kBRegSizeInBytesLog2);
4613
break;
4614
case kHRegSize:
4615
VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);
4616
break;
4617
case kSRegSize:
4618
VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);
4619
break;
4620
case kDRegSize:
4621
VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);
4622
break;
4623
default:
4624
VIXL_UNIMPLEMENTED();
4625
break;
4626
}
4627
4628
Instr sx = 0;
4629
Instr op = 0xffffffff;
4630
if ((mod == NO_SVE_OFFSET_MODIFIER) || (mod == SVE_LSL)) {
4631
VIXL_ASSERT(zm.IsLaneSizeD());
4632
4633
switch (prefetch_size) {
4634
case kBRegSize:
4635
VIXL_ASSERT(mod == NO_SVE_OFFSET_MODIFIER);
4636
op = PRFB_i_p_bz_d_64_scaled;
4637
break;
4638
case kHRegSize:
4639
VIXL_ASSERT(mod == SVE_LSL);
4640
op = PRFH_i_p_bz_d_64_scaled;
4641
break;
4642
case kSRegSize:
4643
VIXL_ASSERT(mod == SVE_LSL);
4644
op = PRFW_i_p_bz_d_64_scaled;
4645
break;
4646
case kDRegSize:
4647
VIXL_ASSERT(mod == SVE_LSL);
4648
op = PRFD_i_p_bz_d_64_scaled;
4649
break;
4650
default:
4651
VIXL_UNIMPLEMENTED();
4652
break;
4653
}
4654
} else {
4655
VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));
4656
VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());
4657
4658
switch (prefetch_size) {
4659
case kBRegSize:
4660
op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_bz_s_x32_scaled)
4661
: static_cast<Instr>(PRFB_i_p_bz_d_x32_scaled);
4662
break;
4663
case kHRegSize:
4664
op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_bz_s_x32_scaled)
4665
: static_cast<Instr>(PRFH_i_p_bz_d_x32_scaled);
4666
break;
4667
case kSRegSize:
4668
op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_bz_s_x32_scaled)
4669
: static_cast<Instr>(PRFW_i_p_bz_d_x32_scaled);
4670
break;
4671
case kDRegSize:
4672
op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_bz_s_x32_scaled)
4673
: static_cast<Instr>(PRFD_i_p_bz_d_x32_scaled);
4674
break;
4675
default:
4676
VIXL_UNIMPLEMENTED();
4677
break;
4678
}
4679
4680
if (mod == SVE_SXTW) {
4681
sx = 1 << 22;
4682
}
4683
}
4684
4685
Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | sx |
4686
RnSP(addr.GetScalarBase()) | Rm(zm));
4687
}
4688
4689
void Assembler::SVEPrefetchHelper(PrefetchOperation prfop,
4690
const PRegister& pg,
4691
const SVEMemOperand& addr,
4692
int prefetch_size) {
4693
if (addr.IsVectorPlusImmediate()) {
4694
// For example:
4695
// [z0.s, #0]
4696
SVEGatherPrefetchVectorPlusImmediateHelper(prfop, pg, addr, prefetch_size);
4697
4698
} else if (addr.IsScalarPlusImmediate()) {
4699
// For example:
4700
// [x0, #42, mul vl]
4701
SVEGatherPrefetchScalarPlusImmediateHelper(prfop, pg, addr, prefetch_size);
4702
4703
} else if (addr.IsScalarPlusVector()) {
4704
// For example:
4705
// [x0, z0.s, sxtw]
4706
SVEContiguousPrefetchScalarPlusVectorHelper(prfop, pg, addr, prefetch_size);
4707
4708
} else if (addr.IsScalarPlusScalar()) {
4709
// For example:
4710
// [x0, x1]
4711
SVEContiguousPrefetchScalarPlusScalarHelper(prfop, pg, addr, prefetch_size);
4712
4713
} else {
4714
VIXL_UNIMPLEMENTED();
4715
}
4716
}
4717
4718
void Assembler::prfb(PrefetchOperation prfop,
4719
const PRegister& pg,
4720
const SVEMemOperand& addr) {
4721
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4722
SVEPrefetchHelper(prfop, pg, addr, kBRegSize);
4723
}
4724
4725
void Assembler::prfd(PrefetchOperation prfop,
4726
const PRegister& pg,
4727
const SVEMemOperand& addr) {
4728
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4729
SVEPrefetchHelper(prfop, pg, addr, kDRegSize);
4730
}
4731
4732
void Assembler::prfh(PrefetchOperation prfop,
4733
const PRegister& pg,
4734
const SVEMemOperand& addr) {
4735
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4736
SVEPrefetchHelper(prfop, pg, addr, kHRegSize);
4737
}
4738
4739
void Assembler::prfw(PrefetchOperation prfop,
4740
const PRegister& pg,
4741
const SVEMemOperand& addr) {
4742
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4743
SVEPrefetchHelper(prfop, pg, addr, kSRegSize);
4744
}
4745
4746
void Assembler::SVELd1St1ScaImmHelper(const ZRegister& zt,
4747
const PRegister& pg,
4748
const SVEMemOperand& addr,
4749
Instr regoffset_op,
4750
Instr immoffset_op,
4751
int imm_divisor) {
4752
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4753
VIXL_ASSERT(addr.IsScalarPlusScalar() || addr.IsScalarPlusImmediate());
4754
4755
Instr op;
4756
if (addr.IsScalarPlusScalar()) {
4757
op = regoffset_op | Rm(addr.GetScalarOffset());
4758
} else {
4759
int64_t imm = addr.GetImmediateOffset();
4760
VIXL_ASSERT(((imm % imm_divisor) == 0) && IsInt4(imm / imm_divisor));
4761
op = immoffset_op | ImmField<19, 16>(imm / imm_divisor);
4762
}
4763
Emit(op | Rt(zt) | PgLow8(pg) | RnSP(addr.GetScalarBase()));
4764
}
4765
4766
void Assembler::SVELd1VecScaHelper(const ZRegister& zt,
4767
const PRegister& pg,
4768
const SVEMemOperand& addr,
4769
uint32_t msize_bytes_log2,
4770
bool is_signed) {
4771
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
4772
VIXL_ASSERT(addr.IsVectorPlusScalar());
4773
ZRegister zn = addr.GetVectorBase();
4774
VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4775
VIXL_ASSERT(AreSameLaneSize(zn, zt));
4776
4777
uint32_t esize = zn.GetLaneSizeInBytesLog2();
4778
uint32_t b14_13 = 0;
4779
if (!is_signed) b14_13 = zn.IsLaneSizeS() ? 0x1 : 0x2;
4780
4781
Instr op = 0x04008000; // LDNT1 with vector plus scalar addressing mode.
4782
op |= (esize << 30) | (msize_bytes_log2 << 23) | (b14_13 << 13);
4783
Emit(op | Rt(zt) | PgLow8(pg) |
4784
SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));
4785
}
4786
4787
void Assembler::SVESt1VecScaHelper(const ZRegister& zt,
4788
const PRegister& pg,
4789
const SVEMemOperand& addr,
4790
uint32_t msize_bytes_log2) {
4791
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
4792
VIXL_ASSERT(addr.IsVectorPlusScalar());
4793
ZRegister zn = addr.GetVectorBase();
4794
VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
4795
VIXL_ASSERT(AreSameLaneSize(zn, zt));
4796
4797
uint32_t bit22 = zn.IsLaneSizeS() ? (1 << 22) : 0;
4798
Instr op = 0xe4002000; // STNT1 with vector plus scalar addressing mode.
4799
op |= bit22 | (msize_bytes_log2 << 23);
4800
Emit(op | Rt(zt) | PgLow8(pg) |
4801
SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));
4802
}
4803
4804
#define VIXL_SVE_LD1R_LIST(V) \
4805
V(qb, 0, B, LD1RQB_z_p_br_contiguous, LD1RQB_z_p_bi_u8, 16) \
4806
V(qh, 1, H, LD1RQH_z_p_br_contiguous, LD1RQH_z_p_bi_u16, 16) \
4807
V(qw, 2, S, LD1RQW_z_p_br_contiguous, LD1RQW_z_p_bi_u32, 16) \
4808
V(qd, 3, D, LD1RQD_z_p_br_contiguous, LD1RQD_z_p_bi_u64, 16) \
4809
V(ob, 0, B, 0xa4200000, 0xa4202000, 32) \
4810
V(oh, 1, H, 0xa4a00000, 0xa4a02000, 32) \
4811
V(ow, 2, S, 0xa5200000, 0xa5202000, 32) \
4812
V(od, 3, D, 0xa5a00000, 0xa5a02000, 32)
4813
4814
#define VIXL_DEFINE_ASM_FUNC(FN, SH, SZ, SCA, IMM, BYTES) \
4815
void Assembler::ld1r##FN(const ZRegister& zt, \
4816
const PRegisterZ& pg, \
4817
const SVEMemOperand& addr) { \
4818
VIXL_ASSERT((BYTES == 16) || \
4819
((BYTES == 32) && (CPUHas(CPUFeatures::kSVEF64MM)))); \
4820
VIXL_ASSERT(addr.IsScalarPlusImmediate() || addr.IsEquivalentToLSL(SH)); \
4821
VIXL_ASSERT(zt.IsLaneSize##SZ()); \
4822
SVELd1St1ScaImmHelper(zt, pg, addr, SCA, IMM, BYTES); \
4823
}
4824
VIXL_SVE_LD1R_LIST(VIXL_DEFINE_ASM_FUNC)
4825
#undef VIXL_DEFINE_ASM_FUNC
4826
#undef VIXL_SVE_LD1R_LIST
4827
4828
#define VIXL_DEFINE_LDFF1(MSZ, LANE_SIZE) \
4829
void Assembler::ldff1##MSZ(const ZRegister& zt, \
4830
const PRegisterZ& pg, \
4831
const SVEMemOperand& addr) { \
4832
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4833
SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \
4834
}
4835
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LDFF1)
4836
4837
#define VIXL_DEFINE_LDFF1S(MSZ, LANE_SIZE) \
4838
void Assembler::ldff1s##MSZ(const ZRegister& zt, \
4839
const PRegisterZ& pg, \
4840
const SVEMemOperand& addr) { \
4841
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
4842
SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \
4843
}
4844
VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LDFF1S)
4845
4846
void Assembler::ldnf1b(const ZRegister& zt,
4847
const PRegisterZ& pg,
4848
const SVEMemOperand& addr) {
4849
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4850
VIXL_ASSERT(addr.IsPlainRegister() ||
4851
(addr.IsScalarPlusImmediate() &&
4852
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4853
4854
SVELdSt1Helper(0,
4855
zt,
4856
pg,
4857
addr,
4858
/* is_signed = */ false,
4859
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4860
}
4861
4862
void Assembler::ldnf1d(const ZRegister& zt,
4863
const PRegisterZ& pg,
4864
const SVEMemOperand& addr) {
4865
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4866
VIXL_ASSERT(addr.IsPlainRegister() ||
4867
(addr.IsScalarPlusImmediate() &&
4868
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4869
4870
SVELdSt1Helper(3,
4871
zt,
4872
pg,
4873
addr,
4874
/* is_signed = */ false,
4875
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4876
}
4877
4878
void Assembler::ldnf1h(const ZRegister& zt,
4879
const PRegisterZ& pg,
4880
const SVEMemOperand& addr) {
4881
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4882
VIXL_ASSERT(addr.IsPlainRegister() ||
4883
(addr.IsScalarPlusImmediate() &&
4884
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4885
4886
SVELdSt1Helper(1,
4887
zt,
4888
pg,
4889
addr,
4890
/* is_signed = */ false,
4891
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4892
}
4893
4894
void Assembler::ldnf1sb(const ZRegister& zt,
4895
const PRegisterZ& pg,
4896
const SVEMemOperand& addr) {
4897
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4898
VIXL_ASSERT(addr.IsPlainRegister() ||
4899
(addr.IsScalarPlusImmediate() &&
4900
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4901
4902
SVELdSt1Helper(0,
4903
zt,
4904
pg,
4905
addr,
4906
/* is_signed = */ true,
4907
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4908
}
4909
4910
void Assembler::ldnf1sh(const ZRegister& zt,
4911
const PRegisterZ& pg,
4912
const SVEMemOperand& addr) {
4913
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4914
VIXL_ASSERT(addr.IsPlainRegister() ||
4915
(addr.IsScalarPlusImmediate() &&
4916
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4917
4918
SVELdSt1Helper(1,
4919
zt,
4920
pg,
4921
addr,
4922
/* is_signed = */ true,
4923
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4924
}
4925
4926
void Assembler::ldnf1sw(const ZRegister& zt,
4927
const PRegisterZ& pg,
4928
const SVEMemOperand& addr) {
4929
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4930
VIXL_ASSERT(addr.IsPlainRegister() ||
4931
(addr.IsScalarPlusImmediate() &&
4932
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4933
4934
SVELdSt1Helper(2,
4935
zt,
4936
pg,
4937
addr,
4938
/* is_signed = */ true,
4939
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4940
}
4941
4942
void Assembler::ldnf1w(const ZRegister& zt,
4943
const PRegisterZ& pg,
4944
const SVEMemOperand& addr) {
4945
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
4946
VIXL_ASSERT(addr.IsPlainRegister() ||
4947
(addr.IsScalarPlusImmediate() &&
4948
(addr.GetOffsetModifier() == SVE_MUL_VL)));
4949
4950
SVELdSt1Helper(2,
4951
zt,
4952
pg,
4953
addr,
4954
/* is_signed = */ false,
4955
SVEContiguousNonFaultLoad_ScalarPlusImmFixed);
4956
}
4957
4958
void Assembler::ldnt1b(const ZRegister& zt,
4959
const PRegisterZ& pg,
4960
const SVEMemOperand& addr) {
4961
VIXL_ASSERT(addr.IsPlainScalar() ||
4962
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4963
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||
4964
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
4965
if (addr.IsVectorPlusScalar()) {
4966
SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ false);
4967
} else {
4968
SVELd1St1ScaImmHelper(zt,
4969
pg,
4970
addr,
4971
LDNT1B_z_p_br_contiguous,
4972
LDNT1B_z_p_bi_contiguous);
4973
}
4974
}
4975
4976
void Assembler::ldnt1d(const ZRegister& zt,
4977
const PRegisterZ& pg,
4978
const SVEMemOperand& addr) {
4979
VIXL_ASSERT(addr.IsPlainScalar() ||
4980
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4981
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||
4982
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
4983
if (addr.IsVectorPlusScalar()) {
4984
SVELd1VecScaHelper(zt, pg, addr, 3, /* is_signed = */ false);
4985
} else {
4986
SVELd1St1ScaImmHelper(zt,
4987
pg,
4988
addr,
4989
LDNT1D_z_p_br_contiguous,
4990
LDNT1D_z_p_bi_contiguous);
4991
}
4992
}
4993
4994
void Assembler::ldnt1h(const ZRegister& zt,
4995
const PRegisterZ& pg,
4996
const SVEMemOperand& addr) {
4997
VIXL_ASSERT(addr.IsPlainScalar() ||
4998
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
4999
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||
5000
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5001
if (addr.IsVectorPlusScalar()) {
5002
SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ false);
5003
} else {
5004
SVELd1St1ScaImmHelper(zt,
5005
pg,
5006
addr,
5007
LDNT1H_z_p_br_contiguous,
5008
LDNT1H_z_p_bi_contiguous);
5009
}
5010
}
5011
5012
void Assembler::ldnt1w(const ZRegister& zt,
5013
const PRegisterZ& pg,
5014
const SVEMemOperand& addr) {
5015
VIXL_ASSERT(addr.IsPlainScalar() ||
5016
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5017
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||
5018
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5019
if (addr.IsVectorPlusScalar()) {
5020
SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ false);
5021
} else {
5022
SVELd1St1ScaImmHelper(zt,
5023
pg,
5024
addr,
5025
LDNT1W_z_p_br_contiguous,
5026
LDNT1W_z_p_bi_contiguous);
5027
}
5028
}
5029
5030
void Assembler::ldnt1sb(const ZRegister& zt,
5031
const PRegisterZ& pg,
5032
const SVEMemOperand& addr) {
5033
VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5034
SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ true);
5035
}
5036
5037
void Assembler::ldnt1sh(const ZRegister& zt,
5038
const PRegisterZ& pg,
5039
const SVEMemOperand& addr) {
5040
VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5041
SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ true);
5042
}
5043
5044
void Assembler::ldnt1sw(const ZRegister& zt,
5045
const PRegisterZ& pg,
5046
const SVEMemOperand& addr) {
5047
VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));
5048
SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ true);
5049
}
5050
5051
Instr Assembler::SVEMemOperandHelper(unsigned msize_in_bytes_log2,
5052
int num_regs,
5053
const SVEMemOperand& addr,
5054
bool is_load) {
5055
VIXL_ASSERT((num_regs >= 1) && (num_regs <= 4));
5056
5057
Instr op = 0xfffffff;
5058
if (addr.IsScalarPlusImmediate()) {
5059
VIXL_ASSERT((addr.GetImmediateOffset() == 0) || addr.IsMulVl());
5060
int64_t imm = addr.GetImmediateOffset();
5061
VIXL_ASSERT((imm % num_regs) == 0);
5062
op = RnSP(addr.GetScalarBase()) | ImmField<19, 16>(imm / num_regs);
5063
5064
} else if (addr.IsScalarPlusScalar()) {
5065
VIXL_ASSERT(addr.GetScalarOffset().IsZero() ||
5066
addr.IsEquivalentToLSL(msize_in_bytes_log2));
5067
op = RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset());
5068
5069
} else if (addr.IsVectorPlusImmediate()) {
5070
ZRegister zn = addr.GetVectorBase();
5071
uint64_t imm = addr.GetImmediateOffset();
5072
VIXL_ASSERT(num_regs == 1);
5073
VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
5074
VIXL_ASSERT(IsMultiple(imm, (1 << msize_in_bytes_log2)));
5075
op = Rn(zn) | ImmUnsignedField<20, 16>(imm >> msize_in_bytes_log2);
5076
} else if (addr.IsVectorPlusScalar()) {
5077
VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);
5078
VIXL_ASSERT(addr.GetShiftAmount() == 0);
5079
ZRegister zn = addr.GetVectorBase();
5080
VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());
5081
Register xm = addr.GetScalarOffset();
5082
op = Rn(zn) | Rm(xm);
5083
} else if (addr.IsScalarPlusVector()) {
5084
// We have to support several different addressing modes. Some instructions
5085
// support a subset of these, but the SVEMemOperand encoding is consistent.
5086
Register xn = addr.GetScalarBase();
5087
ZRegister zm = addr.GetVectorOffset();
5088
SVEOffsetModifier mod = addr.GetOffsetModifier();
5089
Instr modifier_bit = 1 << (is_load ? 22 : 14);
5090
Instr xs = (mod == SVE_SXTW) ? modifier_bit : 0;
5091
VIXL_ASSERT(num_regs == 1);
5092
5093
if (mod == SVE_LSL) {
5094
// 64-bit scaled offset: [<Xn|SP>, <Zm>.D, LSL #<shift>]
5095
VIXL_ASSERT(zm.IsLaneSizeD());
5096
VIXL_ASSERT(addr.GetShiftAmount() == msize_in_bytes_log2);
5097
} else if (mod == NO_SVE_OFFSET_MODIFIER) {
5098
// 64-bit unscaled offset: [<Xn|SP>, <Zm>.D]
5099
VIXL_ASSERT(zm.IsLaneSizeD());
5100
VIXL_ASSERT(addr.GetShiftAmount() == 0);
5101
} else {
5102
// 32-bit scaled offset: [<Xn|SP>, <Zm>.S, <mod> #<shift>]
5103
// 32-bit unscaled offset: [<Xn|SP>, <Zm>.S, <mod>]
5104
// 32-bit unpacked scaled offset: [<Xn|SP>, <Zm>.D, <mod> #<shift>]
5105
// 32-bit unpacked unscaled offset: [<Xn|SP>, <Zm>.D, <mod>]
5106
VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());
5107
VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));
5108
VIXL_ASSERT((addr.GetShiftAmount() == 0) ||
5109
(addr.GetShiftAmount() == msize_in_bytes_log2));
5110
}
5111
5112
// The form itself is encoded in the instruction opcode.
5113
op = RnSP(xn) | Rm(zm) | xs;
5114
} else {
5115
VIXL_UNIMPLEMENTED();
5116
}
5117
5118
return op;
5119
}
5120
5121
// SVEMemStore.
5122
5123
void Assembler::SVESt1Helper(unsigned msize_in_bytes_log2,
5124
const ZRegister& zt,
5125
const PRegister& pg,
5126
const SVEMemOperand& addr) {
5127
if (addr.IsScalarPlusScalar()) {
5128
// Rm must not be xzr.
5129
VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
5130
}
5131
5132
if (addr.IsScatterGather()) {
5133
bool is_load = false;
5134
bool is_signed = false;
5135
bool is_ff = false;
5136
SVEScatterGatherHelper(msize_in_bytes_log2,
5137
zt,
5138
pg,
5139
addr,
5140
is_load,
5141
is_signed,
5142
is_ff);
5143
return;
5144
}
5145
5146
Instr op;
5147
if (addr.IsScalarPlusImmediate()) {
5148
op = SVEContiguousStore_ScalarPlusImmFixed;
5149
} else if (addr.IsScalarPlusScalar()) {
5150
op = SVEContiguousStore_ScalarPlusScalarFixed;
5151
} else {
5152
VIXL_UNIMPLEMENTED();
5153
op = 0xffffffff;
5154
}
5155
SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, false, op);
5156
}
5157
5158
void Assembler::SVESt234Helper(int num_regs,
5159
const ZRegister& zt1,
5160
const PRegister& pg,
5161
const SVEMemOperand& addr) {
5162
if (addr.IsScalarPlusScalar()) {
5163
// Rm must not be xzr.
5164
VIXL_ASSERT(!addr.GetScalarOffset().IsZero());
5165
}
5166
5167
Instr op;
5168
if (addr.IsScalarPlusImmediate()) {
5169
op = SVEStoreMultipleStructures_ScalarPlusImmFixed;
5170
} else if (addr.IsScalarPlusScalar()) {
5171
op = SVEStoreMultipleStructures_ScalarPlusScalarFixed;
5172
} else {
5173
// These instructions don't support any other addressing modes.
5174
VIXL_ABORT();
5175
}
5176
SVELdSt234Helper(num_regs, zt1, pg, addr, op);
5177
}
5178
5179
#define VIXL_DEFINE_ST1(MSZ, LANE_SIZE) \
5180
void Assembler::st1##MSZ(const ZRegister& zt, \
5181
const PRegister& pg, \
5182
const SVEMemOperand& addr) { \
5183
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
5184
SVESt1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr); \
5185
}
5186
#define VIXL_DEFINE_ST2(MSZ, LANE_SIZE) \
5187
void Assembler::st2##MSZ(const ZRegister& zt1, \
5188
const ZRegister& zt2, \
5189
const PRegister& pg, \
5190
const SVEMemOperand& addr) { \
5191
USE(zt2); \
5192
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
5193
VIXL_ASSERT(AreConsecutive(zt1, zt2)); \
5194
VIXL_ASSERT(AreSameFormat(zt1, zt2)); \
5195
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
5196
SVESt234Helper(2, zt1, pg, addr); \
5197
}
5198
#define VIXL_DEFINE_ST3(MSZ, LANE_SIZE) \
5199
void Assembler::st3##MSZ(const ZRegister& zt1, \
5200
const ZRegister& zt2, \
5201
const ZRegister& zt3, \
5202
const PRegister& pg, \
5203
const SVEMemOperand& addr) { \
5204
USE(zt2, zt3); \
5205
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
5206
VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3)); \
5207
VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3)); \
5208
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
5209
SVESt234Helper(3, zt1, pg, addr); \
5210
}
5211
#define VIXL_DEFINE_ST4(MSZ, LANE_SIZE) \
5212
void Assembler::st4##MSZ(const ZRegister& zt1, \
5213
const ZRegister& zt2, \
5214
const ZRegister& zt3, \
5215
const ZRegister& zt4, \
5216
const PRegister& pg, \
5217
const SVEMemOperand& addr) { \
5218
USE(zt2, zt3, zt4); \
5219
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \
5220
VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4)); \
5221
VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4)); \
5222
VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \
5223
SVESt234Helper(4, zt1, pg, addr); \
5224
}
5225
5226
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST1)
5227
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST2)
5228
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST3)
5229
VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST4)
5230
5231
void Assembler::stnt1b(const ZRegister& zt,
5232
const PRegister& pg,
5233
const SVEMemOperand& addr) {
5234
VIXL_ASSERT(addr.IsPlainScalar() ||
5235
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5236
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||
5237
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5238
if (addr.IsVectorPlusScalar()) {
5239
SVESt1VecScaHelper(zt, pg, addr, 0);
5240
} else {
5241
SVELd1St1ScaImmHelper(zt,
5242
pg,
5243
addr,
5244
STNT1B_z_p_br_contiguous,
5245
STNT1B_z_p_bi_contiguous);
5246
}
5247
}
5248
5249
void Assembler::stnt1d(const ZRegister& zt,
5250
const PRegister& pg,
5251
const SVEMemOperand& addr) {
5252
VIXL_ASSERT(addr.IsPlainScalar() ||
5253
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5254
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||
5255
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5256
if (addr.IsVectorPlusScalar()) {
5257
SVESt1VecScaHelper(zt, pg, addr, 3);
5258
} else {
5259
SVELd1St1ScaImmHelper(zt,
5260
pg,
5261
addr,
5262
STNT1D_z_p_br_contiguous,
5263
STNT1D_z_p_bi_contiguous);
5264
}
5265
}
5266
5267
void Assembler::stnt1h(const ZRegister& zt,
5268
const PRegister& pg,
5269
const SVEMemOperand& addr) {
5270
VIXL_ASSERT(addr.IsPlainScalar() ||
5271
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5272
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||
5273
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5274
if (addr.IsVectorPlusScalar()) {
5275
SVESt1VecScaHelper(zt, pg, addr, 1);
5276
} else {
5277
SVELd1St1ScaImmHelper(zt,
5278
pg,
5279
addr,
5280
STNT1H_z_p_br_contiguous,
5281
STNT1H_z_p_bi_contiguous);
5282
}
5283
}
5284
5285
void Assembler::stnt1w(const ZRegister& zt,
5286
const PRegister& pg,
5287
const SVEMemOperand& addr) {
5288
VIXL_ASSERT(addr.IsPlainScalar() ||
5289
(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||
5290
(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||
5291
(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));
5292
if (addr.IsVectorPlusScalar()) {
5293
SVESt1VecScaHelper(zt, pg, addr, 2);
5294
} else {
5295
SVELd1St1ScaImmHelper(zt,
5296
pg,
5297
addr,
5298
STNT1W_z_p_br_contiguous,
5299
STNT1W_z_p_bi_contiguous);
5300
}
5301
}
5302
5303
void Assembler::str(const CPURegister& rt, const SVEMemOperand& addr) {
5304
// STR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]
5305
5306
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5307
VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());
5308
VIXL_ASSERT(addr.IsPlainScalar() ||
5309
(addr.IsScalarPlusImmediate() &&
5310
(addr.GetOffsetModifier() == SVE_MUL_VL)));
5311
int64_t imm9 = addr.GetImmediateOffset();
5312
VIXL_ASSERT(IsInt9(imm9));
5313
Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;
5314
Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;
5315
5316
Instr op = STR_z_bi;
5317
if (rt.IsPRegister()) {
5318
op = STR_p_bi;
5319
}
5320
Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);
5321
}
5322
5323
// SVEMulIndex.
5324
5325
void Assembler::sdot(const ZRegister& zda,
5326
const ZRegister& zn,
5327
const ZRegister& zm,
5328
int index) {
5329
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5330
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
5331
VIXL_ASSERT(AreSameLaneSize(zn, zm));
5332
5333
Instr op = 0xffffffff;
5334
switch (zda.GetLaneSizeInBits()) {
5335
case kSRegSize:
5336
VIXL_ASSERT(IsUint2(index));
5337
op = SDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);
5338
break;
5339
case kDRegSize:
5340
VIXL_ASSERT(IsUint1(index));
5341
op = SDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);
5342
break;
5343
default:
5344
VIXL_UNIMPLEMENTED();
5345
break;
5346
}
5347
5348
Emit(op);
5349
}
5350
5351
void Assembler::udot(const ZRegister& zda,
5352
const ZRegister& zn,
5353
const ZRegister& zm,
5354
int index) {
5355
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5356
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
5357
VIXL_ASSERT(AreSameLaneSize(zn, zm));
5358
5359
Instr op = 0xffffffff;
5360
switch (zda.GetLaneSizeInBits()) {
5361
case kSRegSize:
5362
VIXL_ASSERT(IsUint2(index));
5363
op = UDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);
5364
break;
5365
case kDRegSize:
5366
VIXL_ASSERT(IsUint1(index));
5367
op = UDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);
5368
break;
5369
default:
5370
VIXL_UNIMPLEMENTED();
5371
break;
5372
}
5373
5374
Emit(op);
5375
}
5376
5377
// SVEPartitionBreak.
5378
5379
void Assembler::brka(const PRegisterWithLaneSize& pd,
5380
const PRegister& pg,
5381
const PRegisterWithLaneSize& pn) {
5382
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5383
VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
5384
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5385
5386
Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;
5387
Emit(BRKA_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));
5388
}
5389
5390
void Assembler::brkas(const PRegisterWithLaneSize& pd,
5391
const PRegisterZ& pg,
5392
const PRegisterWithLaneSize& pn) {
5393
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5394
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5395
5396
Emit(BRKAS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5397
}
5398
5399
void Assembler::brkb(const PRegisterWithLaneSize& pd,
5400
const PRegister& pg,
5401
const PRegisterWithLaneSize& pn) {
5402
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5403
VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
5404
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5405
5406
Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;
5407
Emit(BRKB_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));
5408
}
5409
5410
void Assembler::brkbs(const PRegisterWithLaneSize& pd,
5411
const PRegisterZ& pg,
5412
const PRegisterWithLaneSize& pn) {
5413
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5414
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5415
5416
Emit(BRKBS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5417
}
5418
5419
void Assembler::brkn(const PRegisterWithLaneSize& pd,
5420
const PRegisterZ& pg,
5421
const PRegisterWithLaneSize& pn,
5422
const PRegisterWithLaneSize& pm) {
5423
USE(pm);
5424
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5425
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5426
VIXL_ASSERT(pd.Is(pm));
5427
5428
Emit(BRKN_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5429
}
5430
5431
void Assembler::brkns(const PRegisterWithLaneSize& pd,
5432
const PRegisterZ& pg,
5433
const PRegisterWithLaneSize& pn,
5434
const PRegisterWithLaneSize& pm) {
5435
USE(pm);
5436
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5437
VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());
5438
VIXL_ASSERT(pd.Is(pm));
5439
5440
Emit(BRKNS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));
5441
}
5442
5443
// SVEPermutePredicate.
5444
5445
void Assembler::punpkhi(const PRegisterWithLaneSize& pd,
5446
const PRegisterWithLaneSize& pn) {
5447
// PUNPKHI <Pd>.H, <Pn>.B
5448
// 0000 0101 0011 0001 0100 000. ...0 ....
5449
// H<16> = 1 | Pn<8:5> | Pd<3:0>
5450
5451
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5452
VIXL_ASSERT(pd.IsLaneSizeH());
5453
VIXL_ASSERT(pn.IsLaneSizeB());
5454
5455
Emit(PUNPKHI_p_p | Pd(pd) | Pn(pn));
5456
}
5457
5458
void Assembler::punpklo(const PRegisterWithLaneSize& pd,
5459
const PRegisterWithLaneSize& pn) {
5460
// PUNPKLO <Pd>.H, <Pn>.B
5461
// 0000 0101 0011 0000 0100 000. ...0 ....
5462
// H<16> = 0 | Pn<8:5> | Pd<3:0>
5463
5464
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5465
VIXL_ASSERT(pd.IsLaneSizeH());
5466
VIXL_ASSERT(pn.IsLaneSizeB());
5467
5468
Emit(PUNPKLO_p_p | Pd(pd) | Pn(pn));
5469
}
5470
5471
void Assembler::rev(const PRegisterWithLaneSize& pd,
5472
const PRegisterWithLaneSize& pn) {
5473
// REV <Pd>.<T>, <Pn>.<T>
5474
// 0000 0101 ..11 0100 0100 000. ...0 ....
5475
// size<23:22> | Pn<8:5> | Pd<3:0>
5476
5477
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5478
VIXL_ASSERT(AreSameLaneSize(pd, pn));
5479
5480
Emit(REV_p_p | SVESize(pd) | Pd(pd) | Rx<8, 5>(pn));
5481
}
5482
5483
void Assembler::trn1(const PRegisterWithLaneSize& pd,
5484
const PRegisterWithLaneSize& pn,
5485
const PRegisterWithLaneSize& pm) {
5486
// TRN1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5487
// 0000 0101 ..10 .... 0101 000. ...0 ....
5488
// size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5489
5490
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5491
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5492
5493
Emit(TRN1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5494
}
5495
5496
void Assembler::trn2(const PRegisterWithLaneSize& pd,
5497
const PRegisterWithLaneSize& pn,
5498
const PRegisterWithLaneSize& pm) {
5499
// TRN2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5500
// 0000 0101 ..10 .... 0101 010. ...0 ....
5501
// size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5502
5503
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5504
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5505
5506
Emit(TRN2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5507
}
5508
5509
void Assembler::uzp1(const PRegisterWithLaneSize& pd,
5510
const PRegisterWithLaneSize& pn,
5511
const PRegisterWithLaneSize& pm) {
5512
// UZP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5513
// 0000 0101 ..10 .... 0100 100. ...0 ....
5514
// size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5515
5516
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5517
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5518
5519
Emit(UZP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5520
}
5521
5522
void Assembler::uzp2(const PRegisterWithLaneSize& pd,
5523
const PRegisterWithLaneSize& pn,
5524
const PRegisterWithLaneSize& pm) {
5525
// UZP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5526
// 0000 0101 ..10 .... 0100 110. ...0 ....
5527
// size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5528
5529
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5530
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5531
5532
Emit(UZP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5533
}
5534
5535
void Assembler::zip1(const PRegisterWithLaneSize& pd,
5536
const PRegisterWithLaneSize& pn,
5537
const PRegisterWithLaneSize& pm) {
5538
// ZIP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5539
// 0000 0101 ..10 .... 0100 000. ...0 ....
5540
// size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 0 | Pn<8:5> | Pd<3:0>
5541
5542
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5543
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5544
5545
Emit(ZIP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5546
}
5547
5548
void Assembler::zip2(const PRegisterWithLaneSize& pd,
5549
const PRegisterWithLaneSize& pn,
5550
const PRegisterWithLaneSize& pm) {
5551
// ZIP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>
5552
// 0000 0101 ..10 .... 0100 010. ...0 ....
5553
// size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 1 | Pn<8:5> | Pd<3:0>
5554
5555
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5556
VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));
5557
5558
Emit(ZIP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));
5559
}
5560
5561
// SVEPermuteVectorExtract.
5562
5563
void Assembler::ext(const ZRegister& zd,
5564
const ZRegister& zn,
5565
const ZRegister& zm,
5566
unsigned offset) {
5567
// EXT <Zdn>.B, <Zdn>.B, <Zm>.B, #<imm>
5568
// 0000 0101 001. .... 000. .... .... ....
5569
// imm8h<20:16> | imm8l<12:10> | Zm<9:5> | Zdn<4:0>
5570
5571
// EXT <Zd>.B, { <Zn1>.B, <Zn2>.B }, #<imm>
5572
// 0000 0101 011. .... 000. .... .... ....
5573
// imm8h<20:16> | imm8l<12:10> | Zn<9:5> | Zd<4:0>
5574
5575
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5576
VIXL_ASSERT(IsUint8(offset));
5577
5578
int imm8h = ExtractUnsignedBitfield32(7, 3, offset);
5579
int imm8l = ExtractUnsignedBitfield32(2, 0, offset);
5580
5581
Instr op;
5582
if (zd.Is(zn)) {
5583
// Destructive form.
5584
op = EXT_z_zi_des | Rn(zm);
5585
} else {
5586
// Constructive form (requires SVE2).
5587
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2) && AreConsecutive(zn, zm));
5588
op = 0x05600000 | Rn(zn);
5589
}
5590
5591
Emit(op | Rd(zd) | ImmUnsignedField<20, 16>(imm8h) |
5592
ImmUnsignedField<12, 10>(imm8l));
5593
}
5594
5595
// SVEPermuteVectorInterleaving.
5596
5597
void Assembler::trn1(const ZRegister& zd,
5598
const ZRegister& zn,
5599
const ZRegister& zm) {
5600
// TRN1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5601
// 0000 0101 ..1. .... 0111 00.. .... ....
5602
// size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>
5603
5604
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5605
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5606
5607
Emit(TRN1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5608
}
5609
5610
void Assembler::trn2(const ZRegister& zd,
5611
const ZRegister& zn,
5612
const ZRegister& zm) {
5613
// TRN2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5614
// 0000 0101 ..1. .... 0111 01.. .... ....
5615
// size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>
5616
5617
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5618
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5619
5620
Emit(TRN2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5621
}
5622
5623
void Assembler::uzp1(const ZRegister& zd,
5624
const ZRegister& zn,
5625
const ZRegister& zm) {
5626
// UZP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5627
// 0000 0101 ..1. .... 0110 10.. .... ....
5628
// size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>
5629
5630
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5631
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5632
5633
Emit(UZP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5634
}
5635
5636
void Assembler::uzp2(const ZRegister& zd,
5637
const ZRegister& zn,
5638
const ZRegister& zm) {
5639
// UZP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5640
// 0000 0101 ..1. .... 0110 11.. .... ....
5641
// size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>
5642
5643
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5644
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5645
5646
Emit(UZP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5647
}
5648
5649
void Assembler::zip1(const ZRegister& zd,
5650
const ZRegister& zn,
5651
const ZRegister& zm) {
5652
// ZIP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5653
// 0000 0101 ..1. .... 0110 00.. .... ....
5654
// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>
5655
5656
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5657
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5658
5659
Emit(ZIP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5660
}
5661
5662
void Assembler::zip2(const ZRegister& zd,
5663
const ZRegister& zn,
5664
const ZRegister& zm) {
5665
// ZIP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
5666
// 0000 0101 ..1. .... 0110 01.. .... ....
5667
// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>
5668
5669
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5670
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5671
5672
Emit(ZIP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
5673
}
5674
5675
// SVEPermuteVectorPredicated.
5676
5677
void Assembler::clasta(const Register& rd,
5678
const PRegister& pg,
5679
const Register& rn,
5680
const ZRegister& zm) {
5681
// CLASTA <R><dn>, <Pg>, <R><dn>, <Zm>.<T>
5682
// 0000 0101 ..11 0000 101. .... .... ....
5683
// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Rdn<4:0>
5684
5685
USE(rn);
5686
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5687
VIXL_ASSERT(rd.Is(rn));
5688
5689
Emit(CLASTA_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));
5690
}
5691
5692
void Assembler::clasta(const VRegister& vd,
5693
const PRegister& pg,
5694
const VRegister& vn,
5695
const ZRegister& zm) {
5696
// CLASTA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
5697
// 0000 0101 ..10 1010 100. .... .... ....
5698
// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
5699
5700
USE(vn);
5701
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5702
VIXL_ASSERT(vd.Is(vn));
5703
VIXL_ASSERT(vd.IsScalar());
5704
VIXL_ASSERT(AreSameLaneSize(vd, zm));
5705
5706
Emit(CLASTA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
5707
}
5708
5709
void Assembler::clasta(const ZRegister& zd,
5710
const PRegister& pg,
5711
const ZRegister& zn,
5712
const ZRegister& zm) {
5713
// CLASTA <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5714
// 0000 0101 ..10 1000 100. .... .... ....
5715
// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5716
5717
USE(zn);
5718
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5719
VIXL_ASSERT(zd.Is(zn));
5720
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5721
5722
Emit(CLASTA_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5723
}
5724
5725
void Assembler::clastb(const Register& rd,
5726
const PRegister& pg,
5727
const Register& rn,
5728
const ZRegister& zm) {
5729
// CLASTB <R><dn>, <Pg>, <R><dn>, <Zm>.<T>
5730
// 0000 0101 ..11 0001 101. .... .... ....
5731
// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Rdn<4:0>
5732
5733
USE(rn);
5734
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5735
VIXL_ASSERT(rd.Is(rn));
5736
5737
Emit(CLASTB_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));
5738
}
5739
5740
void Assembler::clastb(const VRegister& vd,
5741
const PRegister& pg,
5742
const VRegister& vn,
5743
const ZRegister& zm) {
5744
// CLASTB <V><dn>, <Pg>, <V><dn>, <Zm>.<T>
5745
// 0000 0101 ..10 1011 100. .... .... ....
5746
// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Vdn<4:0>
5747
5748
USE(vn);
5749
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5750
VIXL_ASSERT(vd.Is(vn));
5751
VIXL_ASSERT(vd.IsScalar());
5752
VIXL_ASSERT(AreSameLaneSize(vd, zm));
5753
5754
Emit(CLASTB_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));
5755
}
5756
5757
void Assembler::clastb(const ZRegister& zd,
5758
const PRegister& pg,
5759
const ZRegister& zn,
5760
const ZRegister& zm) {
5761
// CLASTB <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5762
// 0000 0101 ..10 1001 100. .... .... ....
5763
// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5764
5765
USE(zn);
5766
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5767
VIXL_ASSERT(zd.Is(zn));
5768
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5769
5770
Emit(CLASTB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5771
}
5772
5773
void Assembler::compact(const ZRegister& zd,
5774
const PRegister& pg,
5775
const ZRegister& zn) {
5776
// COMPACT <Zd>.<T>, <Pg>, <Zn>.<T>
5777
// 0000 0101 1.10 0001 100. .... .... ....
5778
// sz<22> | Pg<12:10> | Zn<9:5> | Zd<4:0>
5779
5780
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5781
VIXL_ASSERT(AreSameLaneSize(zd, zn));
5782
VIXL_ASSERT((zd.GetLaneSizeInBits() == kSRegSize) ||
5783
(zd.GetLaneSizeInBits() == kDRegSize));
5784
5785
Instr sz = (zd.GetLaneSizeInBits() == kDRegSize) ? (1 << 22) : 0;
5786
Emit(COMPACT_z_p_z | sz | Rd(zd) | PgLow8(pg) | Rn(zn));
5787
}
5788
5789
void Assembler::cpy(const ZRegister& zd,
5790
const PRegisterM& pg,
5791
const Register& rn) {
5792
// CPY <Zd>.<T>, <Pg>/M, <R><n|SP>
5793
// 0000 0101 ..10 1000 101. .... .... ....
5794
// size<23:22> | Pg<12:10> | Rn<9:5> | Zd<4:0>
5795
5796
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5797
VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=
5798
zd.GetLaneSizeInBits());
5799
5800
Emit(CPY_z_p_r | SVESize(zd) | Rd(zd) | PgLow8(pg) | RnSP(rn));
5801
}
5802
5803
void Assembler::cpy(const ZRegister& zd,
5804
const PRegisterM& pg,
5805
const VRegister& vn) {
5806
// CPY <Zd>.<T>, <Pg>/M, <V><n>
5807
// 0000 0101 ..10 0000 100. .... .... ....
5808
// size<23:22> | Pg<12:10> | Vn<9:5> | Zd<4:0>
5809
5810
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5811
VIXL_ASSERT(vn.IsScalar());
5812
VIXL_ASSERT(static_cast<unsigned>(vn.GetSizeInBits()) ==
5813
zd.GetLaneSizeInBits());
5814
5815
Emit(CPY_z_p_v | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(vn));
5816
}
5817
5818
void Assembler::lasta(const Register& rd,
5819
const PRegister& pg,
5820
const ZRegister& zn) {
5821
// LASTA <R><d>, <Pg>, <Zn>.<T>
5822
// 0000 0101 ..10 0000 101. .... .... ....
5823
// size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Rd<4:0>
5824
5825
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5826
5827
Emit(LASTA_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));
5828
}
5829
5830
void Assembler::lasta(const VRegister& vd,
5831
const PRegister& pg,
5832
const ZRegister& zn) {
5833
// LASTA <V><d>, <Pg>, <Zn>.<T>
5834
// 0000 0101 ..10 0010 100. .... .... ....
5835
// size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Vd<4:0>
5836
5837
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5838
VIXL_ASSERT(vd.IsScalar());
5839
5840
Emit(LASTA_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
5841
}
5842
5843
void Assembler::lastb(const Register& rd,
5844
const PRegister& pg,
5845
const ZRegister& zn) {
5846
// LASTB <R><d>, <Pg>, <Zn>.<T>
5847
// 0000 0101 ..10 0001 101. .... .... ....
5848
// size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Rd<4:0>
5849
5850
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5851
5852
Emit(LASTB_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));
5853
}
5854
5855
void Assembler::lastb(const VRegister& vd,
5856
const PRegister& pg,
5857
const ZRegister& zn) {
5858
// LASTB <V><d>, <Pg>, <Zn>.<T>
5859
// 0000 0101 ..10 0011 100. .... .... ....
5860
// size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Vd<4:0>
5861
5862
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5863
VIXL_ASSERT(vd.IsScalar());
5864
5865
Emit(LASTB_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));
5866
}
5867
5868
void Assembler::rbit(const ZRegister& zd,
5869
const PRegisterM& pg,
5870
const ZRegister& zn) {
5871
// RBIT <Zd>.<T>, <Pg>/M, <Zn>.<T>
5872
// 0000 0101 ..10 0111 100. .... .... ....
5873
// size<23:22> | opc<17:16> = 11 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5874
5875
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5876
VIXL_ASSERT(AreSameLaneSize(zd, zn));
5877
5878
Emit(RBIT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5879
}
5880
5881
void Assembler::revb(const ZRegister& zd,
5882
const PRegisterM& pg,
5883
const ZRegister& zn) {
5884
// REVB <Zd>.<T>, <Pg>/M, <Zn>.<T>
5885
// 0000 0101 ..10 0100 100. .... .... ....
5886
// size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5887
5888
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5889
VIXL_ASSERT(AreSameLaneSize(zd, zn));
5890
VIXL_ASSERT(zd.IsLaneSizeH() || zd.IsLaneSizeS() || zd.IsLaneSizeD());
5891
5892
Emit(REVB_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5893
}
5894
5895
void Assembler::revh(const ZRegister& zd,
5896
const PRegisterM& pg,
5897
const ZRegister& zn) {
5898
// REVH <Zd>.<T>, <Pg>/M, <Zn>.<T>
5899
// 0000 0101 ..10 0101 100. .... .... ....
5900
// size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5901
5902
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5903
VIXL_ASSERT(AreSameLaneSize(zd, zn));
5904
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
5905
5906
Emit(REVH_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5907
}
5908
5909
void Assembler::revw(const ZRegister& zd,
5910
const PRegisterM& pg,
5911
const ZRegister& zn) {
5912
// REVW <Zd>.D, <Pg>/M, <Zn>.D
5913
// 0000 0101 ..10 0110 100. .... .... ....
5914
// size<23:22> | opc<17:16> = 10 | Pg<12:10> | Zn<9:5> | Zd<4:0>
5915
5916
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5917
VIXL_ASSERT(AreSameLaneSize(zd, zn));
5918
VIXL_ASSERT(zd.IsLaneSizeD());
5919
5920
Emit(REVW_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
5921
}
5922
5923
void Assembler::splice(const ZRegister& zd,
5924
const PRegister& pg,
5925
const ZRegister& zn,
5926
const ZRegister& zm) {
5927
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5928
5929
if (zd.Aliases(zn)) {
5930
// SPLICE <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>
5931
// 0000 0101 ..10 1100 100. .... .... ....
5932
// size<23:22> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
5933
5934
USE(zn);
5935
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5936
VIXL_ASSERT(zd.Is(zn));
5937
5938
Emit(SPLICE_z_p_zz_des | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
5939
} else {
5940
splice_con(zd, pg, zn, zm);
5941
}
5942
}
5943
5944
void Assembler::splice_con(const ZRegister& zd,
5945
const PRegister& pg,
5946
const ZRegister& zn1,
5947
const ZRegister& zn2) {
5948
// SPLICE <Zd>.<T>, <Pg>, { <Zn1>.<T>, <Zn2>.<T> }
5949
// 0000 0101 ..10 1101 100. .... .... ....
5950
// size<23:22> | Pg<12:10> | Zn<9:5> | Zd<4:0>
5951
5952
USE(zn2);
5953
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
5954
VIXL_ASSERT(AreConsecutive(zn1, zn2));
5955
VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2));
5956
5957
Emit(0x052d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn1));
5958
}
5959
5960
// SVEPermuteVectorUnpredicated.
5961
5962
void Assembler::dup(const ZRegister& zd, const Register& xn) {
5963
// DUP <Zd>.<T>, <R><n|SP>
5964
// 0000 0101 ..10 0000 0011 10.. .... ....
5965
// size<23:22> | Rn<9:5> | Zd<4:0>
5966
5967
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5968
5969
Emit(DUP_z_r | SVESize(zd) | Rd(zd) | RnSP(xn));
5970
}
5971
5972
void Assembler::dup(const ZRegister& zd, const ZRegister& zn, unsigned index) {
5973
// DUP <Zd>.<T>, <Zn>.<T>[<imm>]
5974
// 0000 0101 ..1. .... 0010 00.. .... ....
5975
// imm2<23:22> | tsz<20:16> | Zn<9:5> | Zd<4:0>
5976
5977
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5978
VIXL_ASSERT(AreSameFormat(zd, zn));
5979
VIXL_ASSERT((index * zd.GetLaneSizeInBits()) < 512);
5980
int n = zd.GetLaneSizeInBytesLog2();
5981
unsigned imm_7 = (index << (n + 1)) | (1 << n);
5982
VIXL_ASSERT(IsUint7(imm_7));
5983
unsigned imm_2 = ExtractUnsignedBitfield32(6, 5, imm_7);
5984
unsigned tsz_5 = ExtractUnsignedBitfield32(4, 0, imm_7);
5985
5986
Emit(DUP_z_zi | ImmUnsignedField<23, 22>(imm_2) |
5987
ImmUnsignedField<20, 16>(tsz_5) | Rd(zd) | Rn(zn));
5988
}
5989
5990
void Assembler::insr(const ZRegister& zdn, const Register& rm) {
5991
// INSR <Zdn>.<T>, <R><m>
5992
// 0000 0101 ..10 0100 0011 10.. .... ....
5993
// size<23:22> | Rm<9:5> | Zdn<4:0>
5994
5995
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
5996
5997
Emit(INSR_z_r | SVESize(zdn) | Rd(zdn) | Rn(rm));
5998
}
5999
6000
void Assembler::insr(const ZRegister& zdn, const VRegister& vm) {
6001
// INSR <Zdn>.<T>, <V><m>
6002
// 0000 0101 ..11 0100 0011 10.. .... ....
6003
// size<23:22> | Vm<9:5> | Zdn<4:0>
6004
6005
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6006
VIXL_ASSERT(vm.IsScalar());
6007
6008
Emit(INSR_z_v | SVESize(zdn) | Rd(zdn) | Rn(vm));
6009
}
6010
6011
void Assembler::rev(const ZRegister& zd, const ZRegister& zn) {
6012
// REV <Zd>.<T>, <Zn>.<T>
6013
// 0000 0101 ..11 1000 0011 10.. .... ....
6014
// size<23:22> | Zn<9:5> | Zd<4:0>
6015
6016
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6017
VIXL_ASSERT(AreSameFormat(zd, zn));
6018
6019
Emit(REV_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6020
}
6021
6022
void Assembler::sunpkhi(const ZRegister& zd, const ZRegister& zn) {
6023
// SUNPKHI <Zd>.<T>, <Zn>.<Tb>
6024
// 0000 0101 ..11 0001 0011 10.. .... ....
6025
// size<23:22> | U<17> = 0 | H<16> = 1 | Zn<9:5> | Zd<4:0>
6026
6027
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6028
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6029
VIXL_ASSERT(!zd.IsLaneSizeB());
6030
6031
Emit(SUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6032
}
6033
6034
void Assembler::sunpklo(const ZRegister& zd, const ZRegister& zn) {
6035
// SUNPKLO <Zd>.<T>, <Zn>.<Tb>
6036
// 0000 0101 ..11 0000 0011 10.. .... ....
6037
// size<23:22> | U<17> = 0 | H<16> = 0 | Zn<9:5> | Zd<4:0>
6038
6039
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6040
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6041
VIXL_ASSERT(!zd.IsLaneSizeB());
6042
6043
Emit(SUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6044
}
6045
6046
void Assembler::tbl(const ZRegister& zd,
6047
const ZRegister& zn,
6048
const ZRegister& zm) {
6049
// TBL <Zd>.<T>, { <Zn>.<T> }, <Zm>.<T>
6050
// 0000 0101 ..1. .... 0011 00.. .... ....
6051
// size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>
6052
6053
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6054
VIXL_ASSERT(AreSameFormat(zd, zn, zm));
6055
6056
Emit(TBL_z_zz_1 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6057
}
6058
6059
void Assembler::uunpkhi(const ZRegister& zd, const ZRegister& zn) {
6060
// UUNPKHI <Zd>.<T>, <Zn>.<Tb>
6061
// 0000 0101 ..11 0011 0011 10.. .... ....
6062
// size<23:22> | U<17> = 1 | H<16> = 1 | Zn<9:5> | Zd<4:0>
6063
6064
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6065
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6066
VIXL_ASSERT(!zd.IsLaneSizeB());
6067
6068
Emit(UUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6069
}
6070
6071
void Assembler::uunpklo(const ZRegister& zd, const ZRegister& zn) {
6072
// UUNPKLO <Zd>.<T>, <Zn>.<Tb>
6073
// 0000 0101 ..11 0010 0011 10.. .... ....
6074
// size<23:22> | U<17> = 1 | H<16> = 0 | Zn<9:5> | Zd<4:0>
6075
6076
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6077
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
6078
VIXL_ASSERT(!zd.IsLaneSizeB());
6079
6080
Emit(UUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));
6081
}
6082
6083
// SVEPredicateCount.
6084
6085
void Assembler::cntp(const Register& xd,
6086
const PRegister& pg,
6087
const PRegisterWithLaneSize& pn) {
6088
// CNTP <Xd>, <Pg>, <Pn>.<T>
6089
// 0010 0101 ..10 0000 10.. ..0. .... ....
6090
// size<23:22> | opc<18:16> = 000 | Pg<13:10> | o2<9> = 0 | Pn<8:5> | Rd<4:0>
6091
6092
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6093
VIXL_ASSERT(xd.IsX());
6094
VIXL_ASSERT(pg.IsUnqualified());
6095
if (pg.HasLaneSize()) VIXL_ASSERT(AreSameFormat(pg, pn));
6096
6097
Emit(CNTP_r_p_p | SVESize(pn) | Rd(xd) | Pg<13, 10>(pg) | Pn(pn));
6098
}
6099
6100
// SVEPredicateLogicalOp.
6101
void Assembler::and_(const PRegisterWithLaneSize& pd,
6102
const PRegisterZ& pg,
6103
const PRegisterWithLaneSize& pn,
6104
const PRegisterWithLaneSize& pm) {
6105
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6106
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6107
VIXL_ASSERT(pd.IsLaneSizeB());
6108
Emit(AND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6109
}
6110
6111
void Assembler::ands(const PRegisterWithLaneSize& pd,
6112
const PRegisterZ& pg,
6113
const PRegisterWithLaneSize& pn,
6114
const PRegisterWithLaneSize& pm) {
6115
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6116
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6117
VIXL_ASSERT(pd.IsLaneSizeB());
6118
Emit(ANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6119
}
6120
6121
void Assembler::bic(const PRegisterWithLaneSize& pd,
6122
const PRegisterZ& pg,
6123
const PRegisterWithLaneSize& pn,
6124
const PRegisterWithLaneSize& pm) {
6125
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6126
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6127
VIXL_ASSERT(pd.IsLaneSizeB());
6128
Emit(BIC_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6129
}
6130
6131
void Assembler::bics(const PRegisterWithLaneSize& pd,
6132
const PRegisterZ& pg,
6133
const PRegisterWithLaneSize& pn,
6134
const PRegisterWithLaneSize& pm) {
6135
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6136
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6137
VIXL_ASSERT(pd.IsLaneSizeB());
6138
Emit(BICS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6139
}
6140
6141
void Assembler::eor(const PRegisterWithLaneSize& pd,
6142
const PRegisterZ& pg,
6143
const PRegisterWithLaneSize& pn,
6144
const PRegisterWithLaneSize& pm) {
6145
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6146
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6147
VIXL_ASSERT(pd.IsLaneSizeB());
6148
Emit(EOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6149
}
6150
6151
void Assembler::eors(const PRegisterWithLaneSize& pd,
6152
const PRegisterZ& pg,
6153
const PRegisterWithLaneSize& pn,
6154
const PRegisterWithLaneSize& pm) {
6155
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6156
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6157
VIXL_ASSERT(pd.IsLaneSizeB());
6158
Emit(EORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6159
}
6160
6161
void Assembler::nand(const PRegisterWithLaneSize& pd,
6162
const PRegisterZ& pg,
6163
const PRegisterWithLaneSize& pn,
6164
const PRegisterWithLaneSize& pm) {
6165
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6166
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6167
VIXL_ASSERT(pd.IsLaneSizeB());
6168
Emit(NAND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6169
}
6170
6171
void Assembler::nands(const PRegisterWithLaneSize& pd,
6172
const PRegisterZ& pg,
6173
const PRegisterWithLaneSize& pn,
6174
const PRegisterWithLaneSize& pm) {
6175
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6176
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6177
VIXL_ASSERT(pd.IsLaneSizeB());
6178
Emit(NANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6179
}
6180
6181
void Assembler::nor(const PRegisterWithLaneSize& pd,
6182
const PRegisterZ& pg,
6183
const PRegisterWithLaneSize& pn,
6184
const PRegisterWithLaneSize& pm) {
6185
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6186
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6187
VIXL_ASSERT(pd.IsLaneSizeB());
6188
Emit(NOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6189
}
6190
6191
void Assembler::nors(const PRegisterWithLaneSize& pd,
6192
const PRegisterZ& pg,
6193
const PRegisterWithLaneSize& pn,
6194
const PRegisterWithLaneSize& pm) {
6195
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6196
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6197
VIXL_ASSERT(pd.IsLaneSizeB());
6198
Emit(NORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6199
}
6200
6201
void Assembler::orn(const PRegisterWithLaneSize& pd,
6202
const PRegisterZ& pg,
6203
const PRegisterWithLaneSize& pn,
6204
const PRegisterWithLaneSize& pm) {
6205
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6206
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6207
VIXL_ASSERT(pd.IsLaneSizeB());
6208
Emit(ORN_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6209
}
6210
6211
void Assembler::orns(const PRegisterWithLaneSize& pd,
6212
const PRegisterZ& pg,
6213
const PRegisterWithLaneSize& pn,
6214
const PRegisterWithLaneSize& pm) {
6215
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6216
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6217
VIXL_ASSERT(pd.IsLaneSizeB());
6218
Emit(ORNS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6219
}
6220
6221
void Assembler::orr(const PRegisterWithLaneSize& pd,
6222
const PRegisterZ& pg,
6223
const PRegisterWithLaneSize& pn,
6224
const PRegisterWithLaneSize& pm) {
6225
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6226
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6227
VIXL_ASSERT(pd.IsLaneSizeB());
6228
Emit(ORR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6229
}
6230
6231
void Assembler::orrs(const PRegisterWithLaneSize& pd,
6232
const PRegisterZ& pg,
6233
const PRegisterWithLaneSize& pn,
6234
const PRegisterWithLaneSize& pm) {
6235
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6236
VIXL_ASSERT(AreSameFormat(pd, pn, pm));
6237
VIXL_ASSERT(pd.IsLaneSizeB());
6238
Emit(ORRS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6239
}
6240
6241
void Assembler::sel(const PRegisterWithLaneSize& pd,
6242
const PRegister& pg,
6243
const PRegisterWithLaneSize& pn,
6244
const PRegisterWithLaneSize& pm) {
6245
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6246
Emit(SEL_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6247
}
6248
6249
// SVEPredicateMisc.
6250
6251
void Assembler::pfalse(const PRegisterWithLaneSize& pd) {
6252
// PFALSE <Pd>.B
6253
// 0010 0101 0001 1000 1110 0100 0000 ....
6254
// op<23> = 0 | S<22> = 0 | Pd<3:0>
6255
6256
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6257
// Ignore the lane size, since it makes no difference to the operation.
6258
6259
Emit(PFALSE_p | Pd(pd));
6260
}
6261
6262
void Assembler::pfirst(const PRegisterWithLaneSize& pd,
6263
const PRegister& pg,
6264
const PRegisterWithLaneSize& pn) {
6265
// PFIRST <Pdn>.B, <Pg>, <Pdn>.B
6266
// 0010 0101 0101 1000 1100 000. ...0 ....
6267
// op<23> = 0 | S<22> = 1 | Pg<8:5> | Pdn<3:0>
6268
6269
USE(pn);
6270
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6271
VIXL_ASSERT(pd.Is(pn));
6272
VIXL_ASSERT(pd.IsLaneSizeB());
6273
6274
Emit(PFIRST_p_p_p | Pd(pd) | Pg<8, 5>(pg));
6275
}
6276
6277
void Assembler::pnext(const PRegisterWithLaneSize& pd,
6278
const PRegister& pg,
6279
const PRegisterWithLaneSize& pn) {
6280
// PNEXT <Pdn>.<T>, <Pg>, <Pdn>.<T>
6281
// 0010 0101 ..01 1001 1100 010. ...0 ....
6282
// size<23:22> | Pg<8:5> | Pdn<3:0>
6283
6284
USE(pn);
6285
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6286
VIXL_ASSERT(pd.Is(pn));
6287
6288
Emit(PNEXT_p_p_p | SVESize(pd) | Pd(pd) | Pg<8, 5>(pg));
6289
}
6290
6291
void Assembler::ptest(const PRegister& pg, const PRegisterWithLaneSize& pn) {
6292
// PTEST <Pg>, <Pn>.B
6293
// 0010 0101 0101 0000 11.. ..0. ...0 0000
6294
// op<23> = 0 | S<22> = 1 | Pg<13:10> | Pn<8:5> | opc2<3:0> = 0000
6295
6296
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6297
VIXL_ASSERT(pn.IsLaneSizeB());
6298
6299
Emit(PTEST_p_p | Pg<13, 10>(pg) | Rx<8, 5>(pn));
6300
}
6301
6302
void Assembler::ptrue(const PRegisterWithLaneSize& pd, int pattern) {
6303
// PTRUE <Pd>.<T>{, <pattern>}
6304
// 0010 0101 ..01 1000 1110 00.. ...0 ....
6305
// size<23:22> | S<16> = 0 | pattern<9:5> | Pd<3:0>
6306
6307
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6308
6309
Emit(PTRUE_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));
6310
}
6311
6312
void Assembler::ptrues(const PRegisterWithLaneSize& pd, int pattern) {
6313
// PTRUES <Pd>.<T>{, <pattern>}
6314
// 0010 0101 ..01 1001 1110 00.. ...0 ....
6315
// size<23:22> | S<16> = 1 | pattern<9:5> | Pd<3:0>
6316
6317
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6318
6319
Emit(PTRUES_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));
6320
}
6321
6322
void Assembler::rdffr(const PRegisterWithLaneSize& pd) {
6323
// RDFFR <Pd>.B
6324
// 0010 0101 0001 1001 1111 0000 0000 ....
6325
// op<23> = 0 | S<22> = 0 | Pd<3:0>
6326
6327
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6328
6329
Emit(RDFFR_p_f | Pd(pd));
6330
}
6331
6332
void Assembler::rdffr(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
6333
// RDFFR <Pd>.B, <Pg>/Z
6334
// 0010 0101 0001 1000 1111 000. ...0 ....
6335
// op<23> = 0 | S<22> = 0 | Pg<8:5> | Pd<3:0>
6336
6337
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6338
6339
Emit(RDFFR_p_p_f | Pd(pd) | Pg<8, 5>(pg));
6340
}
6341
6342
void Assembler::rdffrs(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
6343
// RDFFRS <Pd>.B, <Pg>/Z
6344
// 0010 0101 0101 1000 1111 000. ...0 ....
6345
// op<23> = 0 | S<22> = 1 | Pg<8:5> | Pd<3:0>
6346
6347
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6348
6349
Emit(RDFFRS_p_p_f | Pd(pd) | Pg<8, 5>(pg));
6350
}
6351
6352
// SVEPropagateBreak.
6353
6354
void Assembler::brkpa(const PRegisterWithLaneSize& pd,
6355
const PRegisterZ& pg,
6356
const PRegisterWithLaneSize& pn,
6357
const PRegisterWithLaneSize& pm) {
6358
// BRKPA <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6359
// 0010 0101 0000 .... 11.. ..0. ...0 ....
6360
// op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |
6361
// Pd<3:0>
6362
6363
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6364
6365
Emit(BRKPA_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6366
}
6367
6368
void Assembler::brkpas(const PRegisterWithLaneSize& pd,
6369
const PRegisterZ& pg,
6370
const PRegisterWithLaneSize& pn,
6371
const PRegisterWithLaneSize& pm) {
6372
// BRKPAS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6373
// 0010 0101 0100 .... 11.. ..0. ...0 ....
6374
// op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |
6375
// Pd<3:0>
6376
6377
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6378
6379
Emit(BRKPAS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6380
}
6381
6382
void Assembler::brkpb(const PRegisterWithLaneSize& pd,
6383
const PRegisterZ& pg,
6384
const PRegisterWithLaneSize& pn,
6385
const PRegisterWithLaneSize& pm) {
6386
// BRKPB <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6387
// 0010 0101 0000 .... 11.. ..0. ...1 ....
6388
// op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |
6389
// Pd<3:0>
6390
6391
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6392
6393
Emit(BRKPB_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6394
}
6395
6396
void Assembler::brkpbs(const PRegisterWithLaneSize& pd,
6397
const PRegisterZ& pg,
6398
const PRegisterWithLaneSize& pn,
6399
const PRegisterWithLaneSize& pm) {
6400
// BRKPBS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B
6401
// 0010 0101 0100 .... 11.. ..0. ...1 ....
6402
// op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |
6403
// Pd<3:0>
6404
6405
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6406
6407
Emit(BRKPBS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));
6408
}
6409
6410
// SVEStackFrameAdjustment.
6411
6412
void Assembler::addpl(const Register& xd, const Register& xn, int imm6) {
6413
// ADDPL <Xd|SP>, <Xn|SP>, #<imm>
6414
// 0000 0100 011. .... 0101 0... .... ....
6415
// op<22> = 1 | Rn<20:16> | imm6<10:5> | Rd<4:0>
6416
6417
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6418
VIXL_ASSERT(xd.IsX());
6419
VIXL_ASSERT(xn.IsX());
6420
6421
Emit(ADDPL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));
6422
}
6423
6424
void Assembler::addvl(const Register& xd, const Register& xn, int imm6) {
6425
// ADDVL <Xd|SP>, <Xn|SP>, #<imm>
6426
// 0000 0100 001. .... 0101 0... .... ....
6427
// op<22> = 0 | Rn<20:16> | imm6<10:5> | Rd<4:0>
6428
6429
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6430
VIXL_ASSERT(xd.IsX());
6431
VIXL_ASSERT(xn.IsX());
6432
6433
Emit(ADDVL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));
6434
}
6435
6436
// SVEStackFrameSize.
6437
6438
void Assembler::rdvl(const Register& xd, int imm6) {
6439
// RDVL <Xd>, #<imm>
6440
// 0000 0100 1011 1111 0101 0... .... ....
6441
// op<22> = 0 | opc2<20:16> = 11111 | imm6<10:5> | Rd<4:0>
6442
6443
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6444
VIXL_ASSERT(xd.IsX());
6445
6446
Emit(RDVL_r_i | Rd(xd) | ImmField<10, 5>(imm6));
6447
}
6448
6449
// SVEVectorSelect.
6450
6451
void Assembler::sel(const ZRegister& zd,
6452
const PRegister& pg,
6453
const ZRegister& zn,
6454
const ZRegister& zm) {
6455
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6456
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6457
6458
Emit(SEL_z_p_zz | SVESize(zd) | Rd(zd) | Pg<13, 10>(pg) | Rn(zn) | Rm(zm));
6459
}
6460
6461
// SVEWriteFFR.
6462
6463
void Assembler::setffr() {
6464
// SETFFR
6465
// 0010 0101 0010 1100 1001 0000 0000 0000
6466
// opc<23:22> = 00
6467
6468
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6469
6470
Emit(SETFFR_f);
6471
}
6472
6473
void Assembler::wrffr(const PRegisterWithLaneSize& pn) {
6474
// WRFFR <Pn>.B
6475
// 0010 0101 0010 1000 1001 000. ...0 0000
6476
// opc<23:22> = 00 | Pn<8:5>
6477
6478
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6479
6480
Emit(WRFFR_f_p | Rx<8, 5>(pn));
6481
}
6482
6483
// Aliases.
6484
6485
void Assembler::bic(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6486
and_(zd, zn, ~imm);
6487
}
6488
6489
void Assembler::eon(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6490
eor(zd, zn, ~imm);
6491
}
6492
6493
void Assembler::orn(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
6494
orr(zd, zn, ~imm);
6495
}
6496
6497
6498
void Assembler::fmov(const ZRegister& zd, const PRegisterM& pg, double imm) {
6499
if (IsPositiveZero(imm)) {
6500
cpy(zd, pg, 0);
6501
} else {
6502
fcpy(zd, pg, imm);
6503
}
6504
}
6505
6506
void Assembler::fmov(const ZRegister& zd, double imm) {
6507
if (IsPositiveZero(imm)) {
6508
dup(zd, 0);
6509
} else {
6510
fdup(zd, imm);
6511
}
6512
}
6513
6514
void Assembler::mov(const PRegister& pd, const PRegister& pn) {
6515
// If the inputs carry a lane size, they must match.
6516
VIXL_ASSERT((!pd.HasLaneSize() && !pn.HasLaneSize()) ||
6517
AreSameLaneSize(pd, pn));
6518
orr(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());
6519
}
6520
6521
void Assembler::mov(const PRegisterWithLaneSize& pd,
6522
const PRegisterM& pg,
6523
const PRegisterWithLaneSize& pn) {
6524
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6525
sel(pd, pg, pn, pd);
6526
}
6527
6528
void Assembler::mov(const PRegisterWithLaneSize& pd,
6529
const PRegisterZ& pg,
6530
const PRegisterWithLaneSize& pn) {
6531
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6532
and_(pd, pg, pn, pn);
6533
}
6534
6535
void Assembler::mov(const ZRegister& zd,
6536
const PRegister& pg,
6537
int imm8,
6538
int shift) {
6539
VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
6540
cpy(zd, pg, imm8, shift);
6541
}
6542
6543
void Assembler::mov(const ZRegister& zd, const Register& xn) { dup(zd, xn); }
6544
6545
void Assembler::mov(const ZRegister& zd, const VRegister& vn) {
6546
VIXL_ASSERT(vn.IsScalar());
6547
VIXL_ASSERT(AreSameLaneSize(zd, vn));
6548
dup(zd, vn.Z().WithSameLaneSizeAs(vn), 0);
6549
}
6550
6551
void Assembler::mov(const ZRegister& zd, const ZRegister& zn) {
6552
VIXL_ASSERT(AreSameLaneSize(zd, zn));
6553
orr(zd.VnD(), zn.VnD(), zn.VnD());
6554
}
6555
6556
void Assembler::mov(const ZRegister& zd, const ZRegister& zn, unsigned index) {
6557
VIXL_ASSERT(AreSameLaneSize(zd, zn));
6558
dup(zd, zn, index);
6559
}
6560
6561
void Assembler::mov(const ZRegister& zd,
6562
const PRegisterM& pg,
6563
const Register& rn) {
6564
cpy(zd, pg, rn);
6565
}
6566
6567
void Assembler::mov(const ZRegister& zd,
6568
const PRegisterM& pg,
6569
const VRegister& vn) {
6570
VIXL_ASSERT(vn.IsScalar());
6571
VIXL_ASSERT(AreSameLaneSize(zd, vn));
6572
cpy(zd, pg, vn);
6573
}
6574
6575
void Assembler::mov(const ZRegister& zd,
6576
const PRegisterM& pg,
6577
const ZRegister& zn) {
6578
VIXL_ASSERT(AreSameLaneSize(zd, zn));
6579
sel(zd, pg, zn, zd);
6580
}
6581
6582
void Assembler::mov(const ZRegister& zd, uint64_t imm) {
6583
// Mov is an alias of dupm for certain values of imm. Whilst this matters in
6584
// the disassembler, for the assembler, we don't distinguish between the
6585
// two mnemonics, and simply call dupm.
6586
dupm(zd, imm);
6587
}
6588
6589
void Assembler::mov(const ZRegister& zd, int imm8, int shift) {
6590
dup(zd, imm8, shift);
6591
}
6592
6593
void Assembler::movs(const PRegister& pd, const PRegister& pn) {
6594
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6595
orrs(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());
6596
}
6597
6598
void Assembler::movs(const PRegisterWithLaneSize& pd,
6599
const PRegisterZ& pg,
6600
const PRegisterWithLaneSize& pn) {
6601
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6602
ands(pd, pg, pn, pn);
6603
}
6604
6605
void Assembler::not_(const PRegisterWithLaneSize& pd,
6606
const PRegisterZ& pg,
6607
const PRegisterWithLaneSize& pn) {
6608
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6609
eor(pd, pg, pn, pg.VnB());
6610
}
6611
6612
void Assembler::nots(const PRegisterWithLaneSize& pd,
6613
const PRegisterZ& pg,
6614
const PRegisterWithLaneSize& pn) {
6615
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
6616
eors(pd, pg, pn, pg.VnB());
6617
}
6618
6619
// SVE2
6620
6621
void Assembler::adclb(const ZRegister& zda,
6622
const ZRegister& zn,
6623
const ZRegister& zm) {
6624
// ADCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
6625
// 0100 0101 0.0. .... 1101 00.. .... ....
6626
// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
6627
6628
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6629
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6630
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6631
6632
Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
6633
Emit(0x4500d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));
6634
}
6635
6636
void Assembler::adclt(const ZRegister& zda,
6637
const ZRegister& zn,
6638
const ZRegister& zm) {
6639
// ADCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
6640
// 0100 0101 0.0. .... 1101 01.. .... ....
6641
// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
6642
6643
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6644
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6645
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6646
6647
Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
6648
Emit(0x4500d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));
6649
}
6650
6651
void Assembler::addhnb(const ZRegister& zd,
6652
const ZRegister& zn,
6653
const ZRegister& zm) {
6654
// ADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
6655
// 0100 0101 ..1. .... 0110 00.. .... ....
6656
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
6657
6658
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6659
VIXL_ASSERT(AreSameLaneSize(zn, zm));
6660
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
6661
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
6662
6663
Emit(0x45206000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
6664
}
6665
6666
void Assembler::addhnt(const ZRegister& zd,
6667
const ZRegister& zn,
6668
const ZRegister& zm) {
6669
// ADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
6670
// 0100 0101 ..1. .... 0110 01.. .... ....
6671
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
6672
6673
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6674
VIXL_ASSERT(AreSameLaneSize(zn, zm));
6675
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
6676
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
6677
6678
Emit(0x45206400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
6679
}
6680
6681
void Assembler::addp(const ZRegister& zd,
6682
const PRegisterM& pg,
6683
const ZRegister& zn,
6684
const ZRegister& zm) {
6685
// ADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
6686
// 0100 0100 ..01 0001 101. .... .... ....
6687
// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
6688
6689
USE(zn);
6690
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6691
VIXL_ASSERT(zd.Is(zn));
6692
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6693
6694
Emit(0x4411a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
6695
}
6696
6697
void Assembler::bcax(const ZRegister& zd,
6698
const ZRegister& zn,
6699
const ZRegister& zm,
6700
const ZRegister& zk) {
6701
// BCAX <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6702
// 0000 0100 011. .... 0011 10.. .... ....
6703
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6704
6705
USE(zn);
6706
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6707
VIXL_ASSERT(zd.Is(zn));
6708
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6709
VIXL_ASSERT(zd.IsLaneSizeD());
6710
6711
Emit(0x04603800 | Rd(zd) | Rm(zm) | Rn(zk));
6712
}
6713
6714
void Assembler::bdep(const ZRegister& zd,
6715
const ZRegister& zn,
6716
const ZRegister& zm) {
6717
// BDEP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6718
// 0100 0101 ..0. .... 1011 01.. .... ....
6719
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6720
6721
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6722
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6723
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6724
6725
Emit(0x4500b400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6726
}
6727
6728
void Assembler::bext(const ZRegister& zd,
6729
const ZRegister& zn,
6730
const ZRegister& zm) {
6731
// BEXT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6732
// 0100 0101 ..0. .... 1011 00.. .... ....
6733
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6734
6735
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6736
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6737
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6738
6739
Emit(0x4500b000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6740
}
6741
6742
void Assembler::bgrp(const ZRegister& zd,
6743
const ZRegister& zn,
6744
const ZRegister& zm) {
6745
// BGRP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6746
// 0100 0101 ..0. .... 1011 10.. .... ....
6747
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
6748
6749
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6750
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));
6751
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6752
6753
Emit(0x4500b800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6754
}
6755
6756
void Assembler::bsl(const ZRegister& zd,
6757
const ZRegister& zn,
6758
const ZRegister& zm,
6759
const ZRegister& zk) {
6760
// BSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6761
// 0000 0100 001. .... 0011 11.. .... ....
6762
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6763
6764
USE(zn);
6765
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6766
VIXL_ASSERT(zd.Is(zn));
6767
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6768
VIXL_ASSERT(zd.IsLaneSizeD());
6769
6770
Emit(0x04203c00 | Rd(zd) | Rm(zm) | Rn(zk));
6771
}
6772
6773
void Assembler::bsl1n(const ZRegister& zd,
6774
const ZRegister& zn,
6775
const ZRegister& zm,
6776
const ZRegister& zk) {
6777
// BSL1N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6778
// 0000 0100 011. .... 0011 11.. .... ....
6779
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6780
6781
USE(zn);
6782
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6783
VIXL_ASSERT(zd.Is(zn));
6784
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6785
VIXL_ASSERT(zd.IsLaneSizeD());
6786
6787
Emit(0x04603c00 | Rd(zd) | Rm(zm) | Rn(zk));
6788
}
6789
6790
void Assembler::bsl2n(const ZRegister& zd,
6791
const ZRegister& zn,
6792
const ZRegister& zm,
6793
const ZRegister& zk) {
6794
// BSL2N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6795
// 0000 0100 101. .... 0011 11.. .... ....
6796
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6797
6798
USE(zn);
6799
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6800
VIXL_ASSERT(zd.Is(zn));
6801
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6802
VIXL_ASSERT(zd.IsLaneSizeD());
6803
6804
Emit(0x04a03c00 | Rd(zd) | Rm(zm) | Rn(zk));
6805
}
6806
6807
void Assembler::cadd(const ZRegister& zd,
6808
const ZRegister& zn,
6809
const ZRegister& zm,
6810
int rot) {
6811
// CADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>
6812
// 0100 0101 ..00 0000 1101 1... .... ....
6813
// size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>
6814
6815
USE(zn);
6816
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6817
VIXL_ASSERT(zd.Is(zn));
6818
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6819
VIXL_ASSERT((rot == 90) || (rot == 270));
6820
6821
Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);
6822
Emit(0x4500d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));
6823
}
6824
6825
void Assembler::cdot(const ZRegister& zda,
6826
const ZRegister& zn,
6827
const ZRegister& zm,
6828
int index,
6829
int rot) {
6830
// CDOT <Zda>.D, <Zn>.H, <Zm>.H[<imm>], <const>
6831
// 0100 0100 111. .... 0100 .... .... ....
6832
// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6833
6834
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6835
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6836
VIXL_ASSERT(AreSameLaneSize(zn, zm));
6837
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6838
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
6839
VIXL_ASSERT(index >= 0);
6840
6841
Instr zm_and_idx = 0;
6842
if (zm.IsLaneSizeB()) {
6843
// Zm<18:16> | i2<20:19>
6844
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 3));
6845
zm_and_idx = (index << 19) | Rx<18, 16>(zm);
6846
} else {
6847
// Zm<19:16> | i1<20>
6848
VIXL_ASSERT(zm.IsLaneSizeH());
6849
VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 1));
6850
zm_and_idx = (index << 20) | Rx<19, 16>(zm);
6851
}
6852
6853
Instr rotate_bits = (rot / 90) << 10;
6854
Emit(0x44a04000 | zm_and_idx | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn));
6855
}
6856
6857
void Assembler::cdot(const ZRegister& zda,
6858
const ZRegister& zn,
6859
const ZRegister& zm,
6860
int rot) {
6861
// CDOT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>, <const>
6862
// 0100 0100 ..0. .... 0001 .... .... ....
6863
// size<23:22> | Zm<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6864
6865
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6866
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6867
VIXL_ASSERT(AreSameLaneSize(zn, zm));
6868
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
6869
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));
6870
6871
Instr rotate_bits = (rot / 90) << 10;
6872
Emit(0x44001000 | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
6873
}
6874
6875
void Assembler::cmla(const ZRegister& zda,
6876
const ZRegister& zn,
6877
const ZRegister& zm,
6878
int index,
6879
int rot) {
6880
// CMLA <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>
6881
// 0100 0100 101. .... 0110 .... .... ....
6882
// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
6883
6884
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6885
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6886
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6887
6888
Instr rotate_bit = (rot / 90) << 10;
6889
Emit(0x44a06000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |
6890
Rn(zn));
6891
}
6892
6893
void Assembler::cmla(const ZRegister& zda,
6894
const ZRegister& zn,
6895
const ZRegister& zm,
6896
int rot) {
6897
// CMLA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>
6898
// 0100 0100 ..0. .... 0010 .... .... ....
6899
// size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>
6900
6901
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6902
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
6903
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
6904
6905
Instr rotate_bit = (rot / 90) << 10;
6906
Emit(0x44002000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
6907
}
6908
6909
void Assembler::eor3(const ZRegister& zd,
6910
const ZRegister& zn,
6911
const ZRegister& zm,
6912
const ZRegister& zk) {
6913
// EOR3 <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
6914
// 0000 0100 001. .... 0011 10.. .... ....
6915
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
6916
6917
USE(zn);
6918
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6919
VIXL_ASSERT(zd.Is(zn));
6920
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
6921
VIXL_ASSERT(zd.IsLaneSizeD());
6922
6923
Emit(0x04203800 | Rd(zd) | Rm(zm) | Rn(zk));
6924
}
6925
6926
void Assembler::eorbt(const ZRegister& zd,
6927
const ZRegister& zn,
6928
const ZRegister& zm) {
6929
// EORBT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6930
// 0100 0101 ..0. .... 1001 00.. .... ....
6931
// size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>
6932
6933
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6934
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6935
6936
Emit(0x45009000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6937
}
6938
6939
void Assembler::eortb(const ZRegister& zd,
6940
const ZRegister& zn,
6941
const ZRegister& zm) {
6942
// EORTB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
6943
// 0100 0101 ..0. .... 1001 01.. .... ....
6944
// size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>
6945
6946
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6947
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6948
6949
Emit(0x45009400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
6950
}
6951
6952
void Assembler::faddp(const ZRegister& zd,
6953
const PRegisterM& pg,
6954
const ZRegister& zn,
6955
const ZRegister& zm) {
6956
// FADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
6957
// 0110 0100 ..01 0000 100. .... .... ....
6958
// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
6959
6960
USE(zn);
6961
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6962
VIXL_ASSERT(zd.Is(zn));
6963
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
6964
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
6965
6966
Emit(0x64108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
6967
}
6968
6969
void Assembler::fcvtlt(const ZRegister& zd,
6970
const PRegisterM& pg,
6971
const ZRegister& zn) {
6972
// FCVTLT <Zd>.S, <Pg>/M, <Zn>.H
6973
// 0110 0100 1000 1001 101. .... .... ....
6974
// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
6975
6976
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6977
6978
Instr op;
6979
if (zd.IsLaneSizeD() && zn.IsLaneSizeS()) {
6980
op = 0x64cba000;
6981
} else {
6982
VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeH());
6983
op = 0x6489a000;
6984
}
6985
6986
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
6987
}
6988
6989
void Assembler::fcvtnt(const ZRegister& zd,
6990
const PRegisterM& pg,
6991
const ZRegister& zn) {
6992
// FCVTNT <Zd>.S, <Pg>/M, <Zn>.D
6993
// 0110 0100 1100 1010 101. .... .... ....
6994
// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
6995
6996
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
6997
6998
Instr op;
6999
if (zd.IsLaneSizeS() && zn.IsLaneSizeD()) {
7000
op = 0x64caa000;
7001
} else {
7002
VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS());
7003
op = 0x6488a000;
7004
}
7005
Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));
7006
}
7007
7008
void Assembler::fcvtx(const ZRegister& zd,
7009
const PRegisterM& pg,
7010
const ZRegister& zn) {
7011
// FCVTX <Zd>.S, <Pg>/M, <Zn>.D
7012
// 0110 0101 0000 1010 101. .... .... ....
7013
// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7014
7015
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7016
VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeD());
7017
7018
Emit(0x650aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
7019
}
7020
7021
void Assembler::fcvtxnt(const ZRegister& zd,
7022
const PRegisterM& pg,
7023
const ZRegister& zn) {
7024
// FCVTXNT <Zd>.S, <Pg>/M, <Zn>.D
7025
// 0110 0100 0000 1010 101. .... .... ....
7026
// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7027
7028
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7029
7030
Emit(0x640aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
7031
}
7032
7033
void Assembler::flogb(const ZRegister& zd,
7034
const PRegisterM& pg,
7035
const ZRegister& zn) {
7036
// FLOGB <Zd>.<T>, <Pg>/M, <Zn>.<T>
7037
// 0110 0101 0001 1..0 101. .... .... ....
7038
// opc<23:22> | opc2<18:17> | U<16> | Pg<12:10> | Zn<9:5> | Zd<4:0> | size<>
7039
7040
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7041
VIXL_ASSERT(AreSameLaneSize(zd, zn));
7042
VIXL_ASSERT(!zd.IsLaneSizeB());
7043
7044
// Size field is encoded in bits <18:17> rather than <23:22>.
7045
Instr size = SVESize(zd) >> 5;
7046
Emit(0x6518a000 | size | Rd(zd) | PgLow8(pg) | Rn(zn));
7047
}
7048
7049
void Assembler::fmaxnmp(const ZRegister& zd,
7050
const PRegisterM& pg,
7051
const ZRegister& zn,
7052
const ZRegister& zm) {
7053
// FMAXNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7054
// 0110 0100 ..01 0100 100. .... .... ....
7055
// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7056
7057
USE(zn);
7058
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7059
VIXL_ASSERT(zd.Is(zn));
7060
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7061
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7062
7063
Emit(0x64148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7064
}
7065
7066
void Assembler::fmaxp(const ZRegister& zd,
7067
const PRegisterM& pg,
7068
const ZRegister& zn,
7069
const ZRegister& zm) {
7070
// FMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7071
// 0110 0100 ..01 0110 100. .... .... ....
7072
// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7073
7074
USE(zn);
7075
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7076
VIXL_ASSERT(zd.Is(zn));
7077
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7078
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7079
7080
Emit(0x64168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7081
}
7082
7083
void Assembler::fminnmp(const ZRegister& zd,
7084
const PRegisterM& pg,
7085
const ZRegister& zn,
7086
const ZRegister& zm) {
7087
// FMINNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7088
// 0110 0100 ..01 0101 100. .... .... ....
7089
// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7090
7091
USE(zn);
7092
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7093
VIXL_ASSERT(zd.Is(zn));
7094
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7095
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7096
7097
Emit(0x64158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7098
}
7099
7100
void Assembler::fminp(const ZRegister& zd,
7101
const PRegisterM& pg,
7102
const ZRegister& zn,
7103
const ZRegister& zm) {
7104
// FMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7105
// 0110 0100 ..01 0111 100. .... .... ....
7106
// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7107
7108
USE(zn);
7109
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7110
VIXL_ASSERT(zd.Is(zn));
7111
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7112
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7113
7114
Emit(0x64178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7115
}
7116
7117
void Assembler::fmlalb(const ZRegister& zda,
7118
const ZRegister& zn,
7119
const ZRegister& zm) {
7120
// FMLALB <Zda>.S, <Zn>.H, <Zm>.H
7121
// 0110 0100 101. .... 1000 00.. .... ....
7122
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7123
7124
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7125
VIXL_ASSERT(zda.IsLaneSizeS());
7126
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7127
7128
Emit(0x64a08000 | Rd(zda) | Rn(zn) | Rm(zm));
7129
}
7130
7131
void Assembler::fmlalb(const ZRegister& zda,
7132
const ZRegister& zn,
7133
const ZRegister& zm,
7134
int index) {
7135
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7136
VIXL_ASSERT(zda.IsLaneSizeS());
7137
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7138
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7139
Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7140
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7141
7142
Emit(0x64a04000 | Rd(zda) | Rn(zn) | zm_and_idx);
7143
}
7144
7145
void Assembler::fmlalt(const ZRegister& zda,
7146
const ZRegister& zn,
7147
const ZRegister& zm) {
7148
// FMLALT <Zda>.S, <Zn>.H, <Zm>.H
7149
// 0110 0100 101. .... 1000 01.. .... ....
7150
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7151
7152
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7153
VIXL_ASSERT(zda.IsLaneSizeS());
7154
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7155
7156
Emit(0x64a08400 | Rd(zda) | Rn(zn) | Rm(zm));
7157
}
7158
7159
void Assembler::fmlalt(const ZRegister& zda,
7160
const ZRegister& zn,
7161
const ZRegister& zm,
7162
int index) {
7163
// FMLALT <Zda>.S, <Zn>.H, <Zm>.H
7164
// 0110 0100 101. .... 1000 01.. .... ....
7165
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7166
7167
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7168
VIXL_ASSERT(zda.IsLaneSizeS());
7169
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7170
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7171
Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7172
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7173
7174
Emit(0x64a04400 | Rd(zda) | Rn(zn) | zm_and_idx);
7175
}
7176
7177
void Assembler::fmlslb(const ZRegister& zda,
7178
const ZRegister& zn,
7179
const ZRegister& zm) {
7180
// FMLSLB <Zda>.S, <Zn>.H, <Zm>.H
7181
// 0110 0100 101. .... 1010 00.. .... ....
7182
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7183
7184
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7185
VIXL_ASSERT(zda.IsLaneSizeS());
7186
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7187
7188
Emit(0x64a0a000 | Rd(zda) | Rn(zn) | Rm(zm));
7189
}
7190
7191
void Assembler::fmlslb(const ZRegister& zda,
7192
const ZRegister& zn,
7193
const ZRegister& zm,
7194
int index) {
7195
// FMLSLB <Zda>.S, <Zn>.H, <Zm>.H
7196
// 0110 0100 101. .... 1010 00.. .... ....
7197
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7198
7199
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7200
VIXL_ASSERT(zda.IsLaneSizeS());
7201
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7202
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7203
Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7204
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7205
7206
Emit(0x64a06000 | Rd(zda) | Rn(zn) | zm_and_idx);
7207
}
7208
7209
void Assembler::fmlslt(const ZRegister& zda,
7210
const ZRegister& zn,
7211
const ZRegister& zm) {
7212
// FMLSLT <Zda>.S, <Zn>.H, <Zm>.H
7213
// 0110 0100 101. .... 1010 01.. .... ....
7214
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7215
7216
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7217
VIXL_ASSERT(zda.IsLaneSizeS());
7218
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7219
7220
Emit(0x64a0a400 | Rd(zda) | Rn(zn) | Rm(zm));
7221
}
7222
7223
void Assembler::fmlslt(const ZRegister& zda,
7224
const ZRegister& zn,
7225
const ZRegister& zm,
7226
int index) {
7227
// FMLSLT <Zda>.S, <Zn>.H, <Zm>.H
7228
// 0110 0100 101. .... 1010 01.. .... ....
7229
// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>
7230
7231
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7232
VIXL_ASSERT(zda.IsLaneSizeS());
7233
VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());
7234
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
7235
Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
7236
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
7237
7238
Emit(0x64a06400 | Rd(zda) | Rn(zn) | zm_and_idx);
7239
}
7240
7241
void Assembler::histcnt(const ZRegister& zd,
7242
const PRegisterZ& pg,
7243
const ZRegister& zn,
7244
const ZRegister& zm) {
7245
// HISTCNT <Zd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7246
// 0100 0101 ..1. .... 110. .... .... ....
7247
// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7248
7249
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7250
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7251
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());
7252
7253
Emit(0x4520c000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7254
}
7255
7256
void Assembler::histseg(const ZRegister& zd,
7257
const ZRegister& zn,
7258
const ZRegister& zm) {
7259
// HISTSEG <Zd>.B, <Zn>.B, <Zm>.B
7260
// 0100 0101 ..1. .... 1010 00.. .... ....
7261
// size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>
7262
7263
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7264
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7265
VIXL_ASSERT(zd.IsLaneSizeB());
7266
7267
Emit(0x4520a000 | Rd(zd) | Rn(zn) | Rm(zm));
7268
}
7269
7270
void Assembler::match(const PRegisterWithLaneSize& pd,
7271
const PRegisterZ& pg,
7272
const ZRegister& zn,
7273
const ZRegister& zm) {
7274
// MATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7275
// 0100 0101 ..1. .... 100. .... ...0 ....
7276
// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>
7277
7278
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7279
VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));
7280
VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());
7281
7282
Emit(0x45208000 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7283
}
7284
7285
void Assembler::mla(const ZRegister& zda,
7286
const ZRegister& zn,
7287
const ZRegister& zm,
7288
int index) {
7289
// MLA <Zda>.D, <Zn>.D, <Zm>.D[<imm>]
7290
// 0100 0100 111. .... 0000 10.. .... ....
7291
// size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>
7292
7293
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7294
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7295
7296
Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
7297
zm,
7298
index,
7299
0x44200800,
7300
0x44a00800,
7301
0x44e00800);
7302
7303
Emit(synthesised_op | Rd(zda) | Rn(zn));
7304
}
7305
7306
void Assembler::mls(const ZRegister& zda,
7307
const ZRegister& zn,
7308
const ZRegister& zm,
7309
int index) {
7310
// MLS <Zda>.D, <Zn>.D, <Zm>.D[<imm>]
7311
// 0100 0100 111. .... 0000 11.. .... ....
7312
// size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>
7313
7314
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7315
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7316
7317
Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
7318
zm,
7319
index,
7320
0x44200c00,
7321
0x44a00c00,
7322
0x44e00c00);
7323
7324
Emit(synthesised_op | Rd(zda) | Rn(zn));
7325
}
7326
7327
void Assembler::mul(const ZRegister& zd,
7328
const ZRegister& zn,
7329
const ZRegister& zm,
7330
int index) {
7331
// MUL <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
7332
// 0100 0100 111. .... 1111 10.. .... ....
7333
// size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>
7334
7335
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7336
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7337
7338
Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
7339
zm,
7340
index,
7341
0x4420f800,
7342
0x44a0f800,
7343
0x44e0f800);
7344
7345
Emit(synthesised_op | Rd(zd) | Rn(zn));
7346
}
7347
7348
void Assembler::mul(const ZRegister& zd,
7349
const ZRegister& zn,
7350
const ZRegister& zm) {
7351
// MUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
7352
// 0000 0100 ..1. .... 0110 00.. .... ....
7353
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7354
7355
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7356
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7357
7358
Emit(0x04206000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7359
}
7360
7361
void Assembler::nbsl(const ZRegister& zd,
7362
const ZRegister& zn,
7363
const ZRegister& zm,
7364
const ZRegister& zk) {
7365
// NBSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D
7366
// 0000 0100 111. .... 0011 11.. .... ....
7367
// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>
7368
7369
USE(zn);
7370
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7371
VIXL_ASSERT(zd.Is(zn));
7372
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));
7373
VIXL_ASSERT(zd.IsLaneSizeD());
7374
7375
Emit(0x04e03c00 | Rd(zd) | Rm(zm) | Rn(zk));
7376
}
7377
7378
void Assembler::nmatch(const PRegisterWithLaneSize& pd,
7379
const PRegisterZ& pg,
7380
const ZRegister& zn,
7381
const ZRegister& zm) {
7382
// NMATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
7383
// 0100 0101 ..1. .... 100. .... ...1 ....
7384
// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>
7385
7386
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7387
VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));
7388
VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());
7389
7390
Emit(0x45208010 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));
7391
}
7392
7393
void Assembler::pmul(const ZRegister& zd,
7394
const ZRegister& zn,
7395
const ZRegister& zm) {
7396
// PMUL <Zd>.B, <Zn>.B, <Zm>.B
7397
// 0000 0100 001. .... 0110 01.. .... ....
7398
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7399
7400
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7401
7402
Emit(0x04206400 | Rd(zd) | Rn(zn) | Rm(zm));
7403
}
7404
7405
void Assembler::pmullb(const ZRegister& zd,
7406
const ZRegister& zn,
7407
const ZRegister& zm) {
7408
// PMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7409
// 0100 0101 ..0. .... 0110 10.. .... ....
7410
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7411
7412
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7413
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7414
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
7415
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7416
// SVEPmull128 is not supported
7417
VIXL_ASSERT(!zd.IsLaneSizeQ());
7418
7419
Emit(0x45006800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7420
}
7421
7422
void Assembler::pmullt(const ZRegister& zd,
7423
const ZRegister& zn,
7424
const ZRegister& zm) {
7425
// PMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7426
// 0100 0101 ..0. .... 0110 11.. .... ....
7427
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7428
7429
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7430
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7431
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
7432
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7433
// SVEPmull128 is not supported
7434
VIXL_ASSERT(!zd.IsLaneSizeQ());
7435
7436
Emit(0x45006c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7437
}
7438
7439
void Assembler::raddhnb(const ZRegister& zd,
7440
const ZRegister& zn,
7441
const ZRegister& zm) {
7442
// RADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7443
// 0100 0101 ..1. .... 0110 10.. .... ....
7444
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7445
7446
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7447
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7448
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7449
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7450
7451
Emit(0x45206800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7452
}
7453
7454
void Assembler::raddhnt(const ZRegister& zd,
7455
const ZRegister& zn,
7456
const ZRegister& zm) {
7457
// RADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7458
// 0100 0101 ..1. .... 0110 11.. .... ....
7459
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7460
7461
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7462
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7463
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7464
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7465
7466
Emit(0x45206c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7467
}
7468
7469
#define VIXL_SVE_SHR_LIST(V) \
7470
V(rshrnb, 0x45201800) \
7471
V(rshrnt, 0x45201c00) \
7472
V(shrnb, 0x45201000) \
7473
V(shrnt, 0x45201400) \
7474
V(sqrshrnb, 0x45202800) \
7475
V(sqrshrnt, 0x45202c00) \
7476
V(sqrshrunb, 0x45200800) \
7477
V(sqrshrunt, 0x45200c00) \
7478
V(sqshrnb, 0x45202000) \
7479
V(sqshrnt, 0x45202400) \
7480
V(sqshrunb, 0x45200000) \
7481
V(sqshrunt, 0x45200400) \
7482
V(uqrshrnb, 0x45203800) \
7483
V(uqrshrnt, 0x45203c00) \
7484
V(uqshrnb, 0x45203000) \
7485
V(uqshrnt, 0x45203400)
7486
7487
#define VIXL_DEFINE_ASM_FUNC(MNE, X) \
7488
void Assembler::MNE(const ZRegister& zd, const ZRegister& zn, int shift) { \
7489
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); \
7490
VIXL_ASSERT(!zd.IsLaneSizeD() && !zd.IsLaneSizeQ()); \
7491
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2)); \
7492
Instr encoded_imm = \
7493
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits()); \
7494
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, X); \
7495
}
7496
VIXL_SVE_SHR_LIST(VIXL_DEFINE_ASM_FUNC)
7497
#undef VIXL_DEFINE_ASM_FUNC
7498
7499
void Assembler::rsubhnb(const ZRegister& zd,
7500
const ZRegister& zn,
7501
const ZRegister& zm) {
7502
// RSUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7503
// 0100 0101 ..1. .... 0111 10.. .... ....
7504
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7505
7506
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7507
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7508
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7509
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7510
7511
Emit(0x45207800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7512
}
7513
7514
void Assembler::rsubhnt(const ZRegister& zd,
7515
const ZRegister& zn,
7516
const ZRegister& zm) {
7517
// RSUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7518
// 0100 0101 ..1. .... 0111 11.. .... ....
7519
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
7520
7521
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7522
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7523
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
7524
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
7525
7526
Emit(0x45207c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
7527
}
7528
7529
void Assembler::saba(const ZRegister& zda,
7530
const ZRegister& zn,
7531
const ZRegister& zm) {
7532
// SABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7533
// 0100 0101 ..0. .... 1111 10.. .... ....
7534
// size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>
7535
7536
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7537
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7538
7539
Emit(0x4500f800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7540
}
7541
7542
void Assembler::sabalb(const ZRegister& zda,
7543
const ZRegister& zn,
7544
const ZRegister& zm) {
7545
// SABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7546
// 0100 0101 ..0. .... 1100 00.. .... ....
7547
// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7548
7549
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7550
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7551
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7552
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7553
7554
Emit(0x4500c000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7555
}
7556
7557
void Assembler::sabalt(const ZRegister& zda,
7558
const ZRegister& zn,
7559
const ZRegister& zm) {
7560
// SABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7561
// 0100 0101 ..0. .... 1100 01.. .... ....
7562
// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7563
7564
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7565
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7566
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7567
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7568
7569
Emit(0x4500c400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7570
}
7571
7572
void Assembler::sabdlb(const ZRegister& zd,
7573
const ZRegister& zn,
7574
const ZRegister& zm) {
7575
// SABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7576
// 0100 0101 ..0. .... 0011 00.. .... ....
7577
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7578
// Zd<4:0>
7579
7580
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7581
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7582
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7583
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7584
7585
Emit(0x45003000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7586
}
7587
7588
void Assembler::sabdlt(const ZRegister& zd,
7589
const ZRegister& zn,
7590
const ZRegister& zm) {
7591
// SABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7592
// 0100 0101 ..0. .... 0011 01.. .... ....
7593
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7594
// Zd<4:0>
7595
7596
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7597
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7598
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7599
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7600
7601
Emit(0x45003400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7602
}
7603
7604
void Assembler::sadalp(const ZRegister& zda,
7605
const PRegisterM& pg,
7606
const ZRegister& zn) {
7607
// SADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
7608
// 0100 0100 ..00 0100 101. .... .... ....
7609
// size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>
7610
7611
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7612
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7613
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
7614
7615
Emit(0x4404a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));
7616
}
7617
7618
void Assembler::saddlb(const ZRegister& zd,
7619
const ZRegister& zn,
7620
const ZRegister& zm) {
7621
// SADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7622
// 0100 0101 ..0. .... 0000 00.. .... ....
7623
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7624
// Zd<4:0>
7625
7626
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7627
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7628
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7629
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7630
7631
Emit(0x45000000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7632
}
7633
7634
void Assembler::saddlbt(const ZRegister& zd,
7635
const ZRegister& zn,
7636
const ZRegister& zm) {
7637
// SADDLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7638
// 0100 0101 ..0. .... 1000 00.. .... ....
7639
// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
7640
7641
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7642
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7643
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7644
VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
7645
7646
Emit(0x45008000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7647
}
7648
7649
void Assembler::saddlt(const ZRegister& zd,
7650
const ZRegister& zn,
7651
const ZRegister& zm) {
7652
// SADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7653
// 0100 0101 ..0. .... 0000 01.. .... ....
7654
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
7655
// Zd<4:0>
7656
7657
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7658
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7659
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7660
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7661
7662
Emit(0x45000400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7663
}
7664
7665
void Assembler::saddwb(const ZRegister& zd,
7666
const ZRegister& zn,
7667
const ZRegister& zm) {
7668
// SADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
7669
// 0100 0101 ..0. .... 0100 00.. .... ....
7670
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7671
7672
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7673
VIXL_ASSERT(AreSameLaneSize(zd, zn));
7674
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
7675
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7676
7677
Emit(0x45004000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7678
}
7679
7680
void Assembler::saddwt(const ZRegister& zd,
7681
const ZRegister& zn,
7682
const ZRegister& zm) {
7683
// SADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
7684
// 0100 0101 ..0. .... 0100 01.. .... ....
7685
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7686
7687
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7688
VIXL_ASSERT(AreSameLaneSize(zd, zn));
7689
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
7690
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
7691
7692
Emit(0x45004400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7693
}
7694
7695
void Assembler::sbclb(const ZRegister& zda,
7696
const ZRegister& zn,
7697
const ZRegister& zm) {
7698
// SBCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7699
// 0100 0101 1.0. .... 1101 00.. .... ....
7700
// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
7701
7702
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7703
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7704
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
7705
7706
Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
7707
Emit(0x4580d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));
7708
}
7709
7710
void Assembler::sbclt(const ZRegister& zda,
7711
const ZRegister& zn,
7712
const ZRegister& zm) {
7713
// SBCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
7714
// 0100 0101 1.0. .... 1101 01.. .... ....
7715
// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>
7716
7717
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7718
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
7719
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
7720
7721
Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;
7722
Emit(0x4580d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));
7723
}
7724
7725
void Assembler::shadd(const ZRegister& zd,
7726
const PRegisterM& pg,
7727
const ZRegister& zn,
7728
const ZRegister& zm) {
7729
// SHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7730
// 0100 0100 ..01 0000 100. .... .... ....
7731
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7732
7733
USE(zn);
7734
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7735
VIXL_ASSERT(zd.Is(zn));
7736
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7737
7738
Emit(0x44108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7739
}
7740
7741
void Assembler::shsub(const ZRegister& zd,
7742
const PRegisterM& pg,
7743
const ZRegister& zn,
7744
const ZRegister& zm) {
7745
// SHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7746
// 0100 0100 ..01 0010 100. .... .... ....
7747
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7748
7749
USE(zn);
7750
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7751
VIXL_ASSERT(zd.Is(zn));
7752
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7753
7754
Emit(0x44128000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7755
}
7756
7757
void Assembler::shsubr(const ZRegister& zd,
7758
const PRegisterM& pg,
7759
const ZRegister& zn,
7760
const ZRegister& zm) {
7761
// SHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7762
// 0100 0100 ..01 0110 100. .... .... ....
7763
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7764
7765
USE(zn);
7766
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7767
VIXL_ASSERT(zd.Is(zn));
7768
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7769
7770
Emit(0x44168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7771
}
7772
7773
void Assembler::sli(const ZRegister& zd, const ZRegister& zn, int shift) {
7774
// SLI <Zd>.<T>, <Zn>.<T>, #<const>
7775
// 0100 0101 ..0. .... 1111 01.. .... ....
7776
// tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>
7777
7778
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7779
VIXL_ASSERT(AreSameLaneSize(zd, zn));
7780
Instr encoded_imm =
7781
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
7782
7783
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f400);
7784
}
7785
7786
void Assembler::smaxp(const ZRegister& zd,
7787
const PRegisterM& pg,
7788
const ZRegister& zn,
7789
const ZRegister& zm) {
7790
// SMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7791
// 0100 0100 ..01 0100 101. .... .... ....
7792
// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7793
7794
USE(zn);
7795
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7796
VIXL_ASSERT(zd.Is(zn));
7797
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7798
7799
Emit(0x4414a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7800
}
7801
7802
void Assembler::sminp(const ZRegister& zd,
7803
const PRegisterM& pg,
7804
const ZRegister& zn,
7805
const ZRegister& zm) {
7806
// SMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7807
// 0100 0100 ..01 0110 101. .... .... ....
7808
// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7809
7810
USE(zn);
7811
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7812
VIXL_ASSERT(zd.Is(zn));
7813
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7814
7815
Emit(0x4416a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7816
}
7817
7818
#define VIXL_SVE_MULL_INDEX_LIST(V) \
7819
V(smullb, 0x44a0c000) \
7820
V(smullt, 0x44a0c400) \
7821
V(umullb, 0x44a0d000) \
7822
V(umullt, 0x44a0d400) \
7823
V(smlalb, 0x44a08000) \
7824
V(smlalt, 0x44a08400) \
7825
V(smlslb, 0x44a0a000) \
7826
V(smlslt, 0x44a0a400) \
7827
V(umlalb, 0x44a09000) \
7828
V(umlalt, 0x44a09400) \
7829
V(umlslb, 0x44a0b000) \
7830
V(umlslt, 0x44a0b400) \
7831
V(sqdmullb, 0x44a0e000) \
7832
V(sqdmullt, 0x44a0e400)
7833
7834
#define VIXL_DEFINE_ASM_FUNC(MNE, OP) \
7835
void Assembler::MNE(const ZRegister& zda, \
7836
const ZRegister& zn, \
7837
const ZRegister& zm, \
7838
int index) { \
7839
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); \
7840
VIXL_ASSERT(AreSameLaneSize(zn, zm)); \
7841
VIXL_ASSERT(zda.IsLaneSizeD() || zda.IsLaneSizeS()); \
7842
VIXL_ASSERT(zda.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2); \
7843
Instr zm_with_index = SVEMulLongIndexHelper(zm, index); \
7844
Emit(OP | SVESize(zda) | Rd(zda) | Rn(zn) | zm_with_index); \
7845
}
7846
VIXL_SVE_MULL_INDEX_LIST(VIXL_DEFINE_ASM_FUNC)
7847
#undef VIXL_DEFINE_ASM_FuNC
7848
7849
void Assembler::smlalb(const ZRegister& zda,
7850
const ZRegister& zn,
7851
const ZRegister& zm) {
7852
// SMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7853
// 0100 0100 ..0. .... 0100 00.. .... ....
7854
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7855
7856
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7857
VIXL_ASSERT(!zda.IsLaneSizeB());
7858
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7859
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7860
7861
Emit(0x44004000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7862
}
7863
7864
void Assembler::smlalt(const ZRegister& zda,
7865
const ZRegister& zn,
7866
const ZRegister& zm) {
7867
// SMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7868
// 0100 0100 ..0. .... 0100 01.. .... ....
7869
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7870
7871
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7872
VIXL_ASSERT(!zda.IsLaneSizeB());
7873
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7874
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7875
7876
Emit(0x44004400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7877
}
7878
7879
void Assembler::smlslb(const ZRegister& zda,
7880
const ZRegister& zn,
7881
const ZRegister& zm) {
7882
// SMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7883
// 0100 0100 ..0. .... 0101 00.. .... ....
7884
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7885
7886
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7887
VIXL_ASSERT(!zda.IsLaneSizeB());
7888
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7889
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7890
7891
Emit(0x44005000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7892
}
7893
7894
void Assembler::smlslt(const ZRegister& zda,
7895
const ZRegister& zn,
7896
const ZRegister& zm) {
7897
// SMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7898
// 0100 0100 ..0. .... 0101 01.. .... ....
7899
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
7900
7901
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7902
VIXL_ASSERT(!zda.IsLaneSizeB());
7903
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7904
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
7905
7906
Emit(0x44005400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
7907
}
7908
7909
void Assembler::smulh(const ZRegister& zd,
7910
const ZRegister& zn,
7911
const ZRegister& zm) {
7912
// SMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
7913
// 0000 0100 ..1. .... 0110 10.. .... ....
7914
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
7915
7916
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7917
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7918
7919
Emit(0x04206800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7920
}
7921
7922
void Assembler::smullb(const ZRegister& zd,
7923
const ZRegister& zn,
7924
const ZRegister& zm) {
7925
// SMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7926
// 0100 0101 ..0. .... 0111 00.. .... ....
7927
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7928
7929
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7930
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7931
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
7932
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7933
7934
Emit(0x45007000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7935
}
7936
7937
void Assembler::smullt(const ZRegister& zd,
7938
const ZRegister& zn,
7939
const ZRegister& zm) {
7940
// SMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
7941
// 0100 0101 ..0. .... 0111 01.. .... ....
7942
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
7943
7944
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7945
VIXL_ASSERT(AreSameLaneSize(zn, zm));
7946
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
7947
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
7948
7949
Emit(0x45007400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
7950
}
7951
7952
void Assembler::sqabs(const ZRegister& zd,
7953
const PRegisterM& pg,
7954
const ZRegister& zn) {
7955
// SQABS <Zd>.<T>, <Pg>/M, <Zn>.<T>
7956
// 0100 0100 ..00 1000 101. .... .... ....
7957
// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
7958
7959
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7960
VIXL_ASSERT(AreSameLaneSize(zd, zn));
7961
7962
Emit(0x4408a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
7963
}
7964
7965
void Assembler::sqadd(const ZRegister& zd,
7966
const PRegisterM& pg,
7967
const ZRegister& zn,
7968
const ZRegister& zm) {
7969
// SQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
7970
// 0100 0100 ..01 1000 100. .... .... ....
7971
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
7972
7973
USE(zn);
7974
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7975
VIXL_ASSERT(zd.Is(zn));
7976
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7977
7978
Emit(0x44188000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
7979
}
7980
7981
void Assembler::sqcadd(const ZRegister& zd,
7982
const ZRegister& zn,
7983
const ZRegister& zm,
7984
int rot) {
7985
// SQCADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>
7986
// 0100 0101 ..00 0001 1101 1... .... ....
7987
// size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>
7988
7989
USE(zn);
7990
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
7991
VIXL_ASSERT(zd.Is(zn));
7992
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
7993
VIXL_ASSERT((rot == 90) || (rot == 270));
7994
7995
Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);
7996
Emit(0x4501d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));
7997
}
7998
7999
// This prototype maps to 2 instruction encodings:
8000
// sqdmlalb_z_zzzi_d
8001
// sqdmlalb_z_zzzi_s
8002
void Assembler::sqdmlalb(const ZRegister& zda,
8003
const ZRegister& zn,
8004
const ZRegister& zm,
8005
int index) {
8006
// SQDMLALB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8007
// 0100 0100 111. .... 0010 .0.. .... ....
8008
// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8009
8010
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8011
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8012
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8013
VIXL_ASSERT(index >= 0);
8014
8015
Instr zm_and_idx = 0;
8016
if (zm.IsLaneSizeH()) {
8017
// Zm<18:16> | i3h<20:19> | i3l<11>
8018
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8019
zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8020
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8021
} else {
8022
// Zm<19:16> | i2h<20> | i2l<11>
8023
VIXL_ASSERT(zm.IsLaneSizeS());
8024
VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8025
zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8026
Rx<19, 16>(zm);
8027
}
8028
8029
Emit(0x44202000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8030
}
8031
8032
void Assembler::sqdmlalb(const ZRegister& zda,
8033
const ZRegister& zn,
8034
const ZRegister& zm) {
8035
// SQDMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8036
// 0100 0100 ..0. .... 0110 00.. .... ....
8037
// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8038
8039
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8040
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8041
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8042
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8043
8044
Emit(0x44006000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8045
}
8046
8047
void Assembler::sqdmlalbt(const ZRegister& zda,
8048
const ZRegister& zn,
8049
const ZRegister& zm) {
8050
// SQDMLALBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8051
// 0100 0100 ..0. .... 0000 10.. .... ....
8052
// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8053
8054
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8055
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8056
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8057
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8058
8059
Emit(0x44000800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8060
}
8061
8062
// This prototype maps to 2 instruction encodings:
8063
// sqdmlalt_z_zzzi_d
8064
// sqdmlalt_z_zzzi_s
8065
void Assembler::sqdmlalt(const ZRegister& zda,
8066
const ZRegister& zn,
8067
const ZRegister& zm,
8068
int index) {
8069
// SQDMLALT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8070
// 0100 0100 111. .... 0010 .1.. .... ....
8071
// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8072
8073
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8074
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8075
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8076
VIXL_ASSERT(index >= 0);
8077
8078
Instr zm_and_idx = 0;
8079
if (zm.IsLaneSizeH()) {
8080
// Zm<18:16> | i3h<20:19> | i3l<11>
8081
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8082
zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8083
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8084
} else {
8085
// Zm<19:16> | i2h<20> | i2l<11>
8086
VIXL_ASSERT(zm.IsLaneSizeS());
8087
VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8088
zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8089
Rx<19, 16>(zm);
8090
}
8091
8092
Emit(0x44202400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8093
}
8094
8095
void Assembler::sqdmlalt(const ZRegister& zda,
8096
const ZRegister& zn,
8097
const ZRegister& zm) {
8098
// SQDMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8099
// 0100 0100 ..0. .... 0110 01.. .... ....
8100
// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8101
8102
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8103
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8104
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8105
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8106
8107
Emit(0x44006400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8108
}
8109
8110
// This prototype maps to 2 instruction encodings:
8111
// sqdmlslb_z_zzzi_d
8112
// sqdmlslb_z_zzzi_s
8113
void Assembler::sqdmlslb(const ZRegister& zda,
8114
const ZRegister& zn,
8115
const ZRegister& zm,
8116
int index) {
8117
// SQDMLSLB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8118
// 0100 0100 111. .... 0011 .0.. .... ....
8119
// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8120
8121
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8122
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8123
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8124
VIXL_ASSERT(index >= 0);
8125
8126
Instr zm_and_idx = 0;
8127
if (zm.IsLaneSizeH()) {
8128
// Zm<18:16> | i3h<20:19> | i3l<11>
8129
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8130
zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8131
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8132
} else {
8133
// Zm<19:16> | i2h<20> | i2l<11>
8134
VIXL_ASSERT(zm.IsLaneSizeS());
8135
VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8136
zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8137
Rx<19, 16>(zm);
8138
}
8139
8140
Emit(0x44203000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8141
}
8142
8143
void Assembler::sqdmlslb(const ZRegister& zda,
8144
const ZRegister& zn,
8145
const ZRegister& zm) {
8146
// SQDMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8147
// 0100 0100 ..0. .... 0110 10.. .... ....
8148
// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8149
8150
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8151
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8152
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8153
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8154
8155
Emit(0x44006800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8156
}
8157
8158
void Assembler::sqdmlslbt(const ZRegister& zda,
8159
const ZRegister& zn,
8160
const ZRegister& zm) {
8161
// SQDMLSLBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8162
// 0100 0100 ..0. .... 0000 11.. .... ....
8163
// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8164
8165
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8166
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8167
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8168
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8169
8170
Emit(0x44000c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8171
}
8172
8173
// This prototype maps to 2 instruction encodings:
8174
// sqdmlslt_z_zzzi_d
8175
// sqdmlslt_z_zzzi_s
8176
void Assembler::sqdmlslt(const ZRegister& zda,
8177
const ZRegister& zn,
8178
const ZRegister& zm,
8179
int index) {
8180
// SQDMLSLT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]
8181
// 0100 0100 111. .... 0011 .1.. .... ....
8182
// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>
8183
8184
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8185
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8186
VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());
8187
VIXL_ASSERT(index >= 0);
8188
8189
Instr zm_and_idx = 0;
8190
if (zm.IsLaneSizeH()) {
8191
// Zm<18:16> | i3h<20:19> | i3l<11>
8192
VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));
8193
zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |
8194
(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);
8195
} else {
8196
// Zm<19:16> | i2h<20> | i2l<11>
8197
VIXL_ASSERT(zm.IsLaneSizeS());
8198
VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));
8199
zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |
8200
Rx<19, 16>(zm);
8201
}
8202
8203
Emit(0x44203400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));
8204
}
8205
8206
void Assembler::sqdmlslt(const ZRegister& zda,
8207
const ZRegister& zn,
8208
const ZRegister& zm) {
8209
// SQDMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8210
// 0100 0100 ..0. .... 0110 11.. .... ....
8211
// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>
8212
8213
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8214
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8215
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8216
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
8217
8218
Emit(0x44006c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8219
}
8220
8221
void Assembler::sqdmulh(const ZRegister& zd,
8222
const ZRegister& zn,
8223
const ZRegister& zm,
8224
int index) {
8225
// SQDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
8226
// 0100 0100 111. .... 1111 00.. .... ....
8227
// size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8228
8229
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8230
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8231
8232
Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
8233
zm,
8234
index,
8235
0x4420f000,
8236
0x44a0f000,
8237
0x44e0f000);
8238
8239
Emit(synthesised_op | Rd(zd) | Rn(zn));
8240
}
8241
8242
void Assembler::sqdmulh(const ZRegister& zd,
8243
const ZRegister& zn,
8244
const ZRegister& zm) {
8245
// SQDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8246
// 0000 0100 ..1. .... 0111 00.. .... ....
8247
// size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8248
8249
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8250
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8251
8252
Emit(0x04207000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8253
}
8254
8255
void Assembler::sqdmullb(const ZRegister& zd,
8256
const ZRegister& zn,
8257
const ZRegister& zm) {
8258
// SQDMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8259
// 0100 0101 ..0. .... 0110 00.. .... ....
8260
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8261
8262
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8263
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8264
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
8265
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
8266
8267
Emit(0x45006000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8268
}
8269
8270
void Assembler::sqdmullt(const ZRegister& zd,
8271
const ZRegister& zn,
8272
const ZRegister& zm) {
8273
// SQDMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8274
// 0100 0101 ..0. .... 0110 01.. .... ....
8275
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8276
8277
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8278
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8279
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
8280
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
8281
8282
Emit(0x45006400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8283
}
8284
8285
void Assembler::sqneg(const ZRegister& zd,
8286
const PRegisterM& pg,
8287
const ZRegister& zn) {
8288
// SQNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>
8289
// 0100 0100 ..00 1001 101. .... .... ....
8290
// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
8291
8292
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8293
VIXL_ASSERT(AreSameLaneSize(zd, zn));
8294
8295
Emit(0x4409a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
8296
}
8297
8298
void Assembler::sqrdcmlah(const ZRegister& zda,
8299
const ZRegister& zn,
8300
const ZRegister& zm,
8301
int index,
8302
int rot) {
8303
// SQRDCMLAH <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>
8304
// 0100 0100 101. .... 0111 .... .... ....
8305
// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>
8306
8307
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8308
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8309
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
8310
8311
Instr rotate_bit = (rot / 90) << 10;
8312
Emit(0x44a07000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |
8313
Rn(zn));
8314
}
8315
8316
void Assembler::sqrdcmlah(const ZRegister& zda,
8317
const ZRegister& zn,
8318
const ZRegister& zm,
8319
int rot) {
8320
// SQRDCMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>
8321
// 0100 0100 ..0. .... 0011 .... .... ....
8322
// size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>
8323
8324
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8325
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8326
VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));
8327
8328
Instr rotate_bit = (rot / 90) << 10;
8329
Emit(0x44003000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8330
}
8331
8332
// This prototype maps to 3 instruction encodings:
8333
// sqrdmlah_z_zzzi_d
8334
// sqrdmlah_z_zzzi_h
8335
// sqrdmlah_z_zzzi_s
8336
void Assembler::sqrdmlah(const ZRegister& zda,
8337
const ZRegister& zn,
8338
const ZRegister& zm,
8339
int index) {
8340
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8341
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8342
8343
Instr op_h = 0x44201000;
8344
Instr op_s = op_h | (1 << 23);
8345
Instr op_d = op_h | (3 << 22);
8346
// The encoding of opcode, index, Zm, and size are synthesized in this
8347
// variable.
8348
Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
8349
zm,
8350
index,
8351
op_h,
8352
op_s,
8353
op_d);
8354
8355
Emit(synthesized_op | Rd(zda) | Rn(zn));
8356
}
8357
8358
void Assembler::sqrdmlah(const ZRegister& zda,
8359
const ZRegister& zn,
8360
const ZRegister& zm) {
8361
// SQRDMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8362
// 0100 0100 ..0. .... 0111 00.. .... ....
8363
// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8364
8365
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8366
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8367
8368
Emit(0x44007000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8369
}
8370
8371
// This prototype maps to 3 instruction encodings:
8372
// sqrdmlsh_z_zzzi_d
8373
// sqrdmlsh_z_zzzi_h
8374
// sqrdmlsh_z_zzzi_s
8375
void Assembler::sqrdmlsh(const ZRegister& zda,
8376
const ZRegister& zn,
8377
const ZRegister& zm,
8378
int index) {
8379
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8380
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8381
8382
Instr op_h = 0x44201400;
8383
Instr op_s = op_h | (1 << 23);
8384
Instr op_d = op_h | (3 << 22);
8385
// The encoding of opcode, index, Zm, and size are synthesized in this
8386
// variable.
8387
Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),
8388
zm,
8389
index,
8390
op_h,
8391
op_s,
8392
op_d);
8393
8394
Emit(synthesized_op | Rd(zda) | Rn(zn));
8395
}
8396
8397
void Assembler::sqrdmlsh(const ZRegister& zda,
8398
const ZRegister& zn,
8399
const ZRegister& zm) {
8400
// SQRDMLSH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8401
// 0100 0100 ..0. .... 0111 01.. .... ....
8402
// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>
8403
8404
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8405
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8406
8407
Emit(0x44007400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
8408
}
8409
8410
void Assembler::sqrdmulh(const ZRegister& zd,
8411
const ZRegister& zn,
8412
const ZRegister& zm,
8413
int index) {
8414
// SQRDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]
8415
// 0100 0100 111. .... 1111 01.. .... ....
8416
// size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8417
8418
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8419
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8420
8421
Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),
8422
zm,
8423
index,
8424
0x4420f400,
8425
0x44a0f400,
8426
0x44e0f400);
8427
8428
Emit(synthesised_op | Rd(zd) | Rn(zn));
8429
}
8430
8431
void Assembler::sqrdmulh(const ZRegister& zd,
8432
const ZRegister& zn,
8433
const ZRegister& zm) {
8434
// SQRDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8435
// 0000 0100 ..1. .... 0111 01.. .... ....
8436
// size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>
8437
8438
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8439
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8440
8441
Emit(0x04207400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8442
}
8443
8444
void Assembler::sqrshl(const ZRegister& zd,
8445
const PRegisterM& pg,
8446
const ZRegister& zn,
8447
const ZRegister& zm) {
8448
// SQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8449
// 0100 0100 ..00 1010 100. .... .... ....
8450
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8451
// Zdn<4:0>
8452
8453
USE(zn);
8454
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8455
VIXL_ASSERT(zd.Is(zn));
8456
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8457
8458
Emit(0x440a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8459
}
8460
8461
void Assembler::sqrshlr(const ZRegister& zd,
8462
const PRegisterM& pg,
8463
const ZRegister& zn,
8464
const ZRegister& zm) {
8465
// SQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8466
// 0100 0100 ..00 1110 100. .... .... ....
8467
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8468
// Zdn<4:0>
8469
8470
USE(zn);
8471
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8472
VIXL_ASSERT(zd.Is(zn));
8473
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8474
8475
Emit(0x440e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8476
}
8477
8478
void Assembler::sqshl(const ZRegister& zd,
8479
const PRegisterM& pg,
8480
const ZRegister& zn,
8481
int shift) {
8482
// SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8483
// 0000 0100 ..00 0110 100. .... .... ....
8484
// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8485
// imm3<7:5> | Zdn<4:0>
8486
8487
USE(zn);
8488
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8489
VIXL_ASSERT(zd.Is(zn));
8490
Instr encoded_imm =
8491
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
8492
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04068000);
8493
}
8494
8495
void Assembler::sqshl(const ZRegister& zd,
8496
const PRegisterM& pg,
8497
const ZRegister& zn,
8498
const ZRegister& zm) {
8499
// SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8500
// 0100 0100 ..00 1000 100. .... .... ....
8501
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8502
// Zdn<4:0>
8503
8504
USE(zn);
8505
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8506
VIXL_ASSERT(zd.Is(zn));
8507
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8508
8509
Emit(0x44088000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8510
}
8511
8512
void Assembler::sqshlr(const ZRegister& zd,
8513
const PRegisterM& pg,
8514
const ZRegister& zn,
8515
const ZRegister& zm) {
8516
// SQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8517
// 0100 0100 ..00 1100 100. .... .... ....
8518
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8519
// Zdn<4:0>
8520
8521
USE(zn);
8522
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8523
VIXL_ASSERT(zd.Is(zn));
8524
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8525
8526
Emit(0x440c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8527
}
8528
8529
void Assembler::sqshlu(const ZRegister& zd,
8530
const PRegisterM& pg,
8531
const ZRegister& zn,
8532
int shift) {
8533
// SQSHLU <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8534
// 0000 0100 ..00 1111 100. .... .... ....
8535
// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8536
// imm3<7:5> | Zdn<4:0>
8537
8538
USE(zn);
8539
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8540
VIXL_ASSERT(zd.Is(zn));
8541
8542
Instr encoded_imm =
8543
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
8544
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040f8000);
8545
}
8546
8547
void Assembler::sqsub(const ZRegister& zd,
8548
const PRegisterM& pg,
8549
const ZRegister& zn,
8550
const ZRegister& zm) {
8551
// SQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8552
// 0100 0100 ..01 1010 100. .... .... ....
8553
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8554
8555
USE(zn);
8556
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8557
VIXL_ASSERT(zd.Is(zn));
8558
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8559
8560
Emit(0x441a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8561
}
8562
8563
void Assembler::sqsubr(const ZRegister& zd,
8564
const PRegisterM& pg,
8565
const ZRegister& zn,
8566
const ZRegister& zm) {
8567
// SQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8568
// 0100 0100 ..01 1110 100. .... .... ....
8569
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8570
8571
USE(zn);
8572
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8573
VIXL_ASSERT(zd.Is(zn));
8574
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8575
8576
Emit(0x441e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8577
}
8578
8579
void Assembler::sqxtnb(const ZRegister& zd, const ZRegister& zn) {
8580
// SQXTNB <Zd>.<T>, <Zn>.<Tb>
8581
// 0100 0101 0.1. .000 0100 00.. .... ....
8582
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8583
8584
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8585
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8586
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8587
8588
// XTN instructions look like immediate shifts with zero shift distance.
8589
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8590
SVEBitwiseShiftImmediate(zd, zn, size, 0x45204000);
8591
}
8592
8593
void Assembler::sqxtnt(const ZRegister& zd, const ZRegister& zn) {
8594
// SQXTNT <Zd>.<T>, <Zn>.<Tb>
8595
// 0100 0101 0.1. .000 0100 01.. .... ....
8596
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8597
8598
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8599
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8600
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8601
8602
// XTN instructions look like immediate shifts with zero shift distance.
8603
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8604
SVEBitwiseShiftImmediate(zd, zn, size, 0x45204400);
8605
}
8606
8607
void Assembler::sqxtunb(const ZRegister& zd, const ZRegister& zn) {
8608
// SQXTUNB <Zd>.<T>, <Zn>.<Tb>
8609
// 0100 0101 0.1. .000 0101 00.. .... ....
8610
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8611
8612
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8613
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8614
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8615
8616
// XTN instructions look like immediate shifts with zero shift distance.
8617
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8618
SVEBitwiseShiftImmediate(zd, zn, size, 0x45205000);
8619
}
8620
8621
void Assembler::sqxtunt(const ZRegister& zd, const ZRegister& zn) {
8622
// SQXTUNT <Zd>.<T>, <Zn>.<Tb>
8623
// 0100 0101 0.1. .000 0101 01.. .... ....
8624
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
8625
8626
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8627
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
8628
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
8629
8630
// XTN instructions look like immediate shifts with zero shift distance.
8631
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
8632
SVEBitwiseShiftImmediate(zd, zn, size, 0x45205400);
8633
}
8634
8635
void Assembler::srhadd(const ZRegister& zd,
8636
const PRegisterM& pg,
8637
const ZRegister& zn,
8638
const ZRegister& zm) {
8639
// SRHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8640
// 0100 0100 ..01 0100 100. .... .... ....
8641
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8642
8643
USE(zn);
8644
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8645
VIXL_ASSERT(zd.Is(zn));
8646
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8647
8648
Emit(0x44148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8649
}
8650
8651
void Assembler::sri(const ZRegister& zd, const ZRegister& zn, int shift) {
8652
// SRI <Zd>.<T>, <Zn>.<T>, #<const>
8653
// 0100 0101 ..0. .... 1111 00.. .... ....
8654
// tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>
8655
8656
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8657
VIXL_ASSERT(AreSameLaneSize(zd, zn));
8658
Instr encoded_imm =
8659
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
8660
8661
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f000);
8662
}
8663
8664
void Assembler::srshl(const ZRegister& zd,
8665
const PRegisterM& pg,
8666
const ZRegister& zn,
8667
const ZRegister& zm) {
8668
// SRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8669
// 0100 0100 ..00 0010 100. .... .... ....
8670
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8671
// Zdn<4:0>
8672
8673
USE(zn);
8674
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8675
VIXL_ASSERT(zd.Is(zn));
8676
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8677
8678
Emit(0x44028000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8679
}
8680
8681
void Assembler::srshlr(const ZRegister& zd,
8682
const PRegisterM& pg,
8683
const ZRegister& zn,
8684
const ZRegister& zm) {
8685
// SRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8686
// 0100 0100 ..00 0110 100. .... .... ....
8687
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
8688
// Zdn<4:0>
8689
8690
USE(zn);
8691
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8692
VIXL_ASSERT(zd.Is(zn));
8693
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8694
8695
Emit(0x44068000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8696
}
8697
8698
void Assembler::srshr(const ZRegister& zd,
8699
const PRegisterM& pg,
8700
const ZRegister& zn,
8701
int shift) {
8702
// SRSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
8703
// 0000 0100 ..00 1100 100. .... .... ....
8704
// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
8705
// imm3<7:5> | Zdn<4:0>
8706
8707
USE(zn);
8708
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8709
VIXL_ASSERT(zd.Is(zn));
8710
Instr encoded_imm =
8711
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
8712
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040c8000);
8713
}
8714
8715
void Assembler::srsra(const ZRegister& zda, const ZRegister& zn, int shift) {
8716
// SRSRA <Zda>.<T>, <Zn>.<T>, #<const>
8717
// 0100 0101 ..0. .... 1110 10.. .... ....
8718
// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
8719
// Zda<4:0>
8720
8721
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8722
VIXL_ASSERT(AreSameLaneSize(zda, zn));
8723
Instr encoded_imm =
8724
EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
8725
8726
SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e800);
8727
}
8728
8729
void Assembler::sshllb(const ZRegister& zd, const ZRegister& zn, int shift) {
8730
// SSHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>
8731
// 0100 0101 0.0. .... 1010 00.. .... ....
8732
// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8733
8734
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8735
VIXL_ASSERT(!zd.IsLaneSizeB());
8736
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8737
8738
Instr encoded_imm =
8739
EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
8740
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a000);
8741
}
8742
8743
void Assembler::sshllt(const ZRegister& zd, const ZRegister& zn, int shift) {
8744
// SSHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>
8745
// 0100 0101 0.0. .... 1010 01.. .... ....
8746
// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8747
8748
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8749
VIXL_ASSERT(!zd.IsLaneSizeB());
8750
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8751
8752
Instr encoded_imm =
8753
EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
8754
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a400);
8755
}
8756
8757
void Assembler::ssra(const ZRegister& zda, const ZRegister& zn, int shift) {
8758
// SSRA <Zda>.<T>, <Zn>.<T>, #<const>
8759
// 0100 0101 ..0. .... 1110 00.. .... ....
8760
// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
8761
// Zda<4:0>
8762
8763
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8764
VIXL_ASSERT(AreSameLaneSize(zda, zn));
8765
Instr encoded_imm =
8766
EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
8767
8768
SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e000);
8769
}
8770
8771
void Assembler::ssublb(const ZRegister& zd,
8772
const ZRegister& zn,
8773
const ZRegister& zm) {
8774
// SSUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8775
// 0100 0101 ..0. .... 0001 00.. .... ....
8776
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
8777
// Zd<4:0>
8778
8779
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8780
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8781
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8782
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8783
8784
Emit(0x45001000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8785
}
8786
8787
void Assembler::ssublbt(const ZRegister& zd,
8788
const ZRegister& zn,
8789
const ZRegister& zm) {
8790
// SSUBLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8791
// 0100 0101 ..0. .... 1000 10.. .... ....
8792
// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
8793
8794
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8795
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8796
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8797
VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
8798
8799
Emit(0x45008800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8800
}
8801
8802
void Assembler::ssublt(const ZRegister& zd,
8803
const ZRegister& zn,
8804
const ZRegister& zm) {
8805
// SSUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8806
// 0100 0101 ..0. .... 0001 01.. .... ....
8807
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
8808
// Zd<4:0>
8809
8810
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8811
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8812
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8813
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8814
8815
Emit(0x45001400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8816
}
8817
8818
void Assembler::ssubltb(const ZRegister& zd,
8819
const ZRegister& zn,
8820
const ZRegister& zm) {
8821
// SSUBLTB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8822
// 0100 0101 ..0. .... 1000 11.. .... ....
8823
// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>
8824
8825
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8826
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8827
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
8828
VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());
8829
8830
Emit(0x45008c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8831
}
8832
8833
void Assembler::ssubwb(const ZRegister& zd,
8834
const ZRegister& zn,
8835
const ZRegister& zm) {
8836
// SSUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
8837
// 0100 0101 ..0. .... 0101 00.. .... ....
8838
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8839
8840
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8841
VIXL_ASSERT(AreSameLaneSize(zd, zn));
8842
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
8843
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8844
8845
Emit(0x45005000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8846
}
8847
8848
void Assembler::ssubwt(const ZRegister& zd,
8849
const ZRegister& zn,
8850
const ZRegister& zm) {
8851
// SSUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
8852
// 0100 0101 ..0. .... 0101 01.. .... ....
8853
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
8854
8855
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8856
VIXL_ASSERT(AreSameLaneSize(zd, zn));
8857
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
8858
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
8859
8860
Emit(0x45005400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8861
}
8862
8863
#if 0
8864
// This prototype maps to 2 instruction encodings:
8865
// stnt1b_z_p_ar_d_64_unscaled
8866
// stnt1b_z_p_ar_s_x32_unscaled
8867
void Assembler::stnt1b(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8868
// STNT1B { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8869
// 1110 0100 000. .... 001. .... .... ....
8870
// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8871
8872
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8873
8874
Emit(0xe4002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8875
}
8876
8877
void Assembler::stnt1d(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8878
// STNT1D { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8879
// 1110 0101 100. .... 001. .... .... ....
8880
// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8881
8882
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8883
8884
Emit(0xe5802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8885
}
8886
8887
// This prototype maps to 2 instruction encodings:
8888
// stnt1h_z_p_ar_d_64_unscaled
8889
// stnt1h_z_p_ar_s_x32_unscaled
8890
void Assembler::stnt1h(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8891
// STNT1H { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8892
// 1110 0100 100. .... 001. .... .... ....
8893
// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8894
8895
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8896
8897
Emit(0xe4802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8898
}
8899
8900
// This prototype maps to 2 instruction encodings:
8901
// stnt1w_z_p_ar_d_64_unscaled
8902
// stnt1w_z_p_ar_s_x32_unscaled
8903
void Assembler::stnt1w(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {
8904
// STNT1W { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]
8905
// 1110 0101 000. .... 001. .... .... ....
8906
// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>
8907
8908
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8909
8910
Emit(0xe5002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));
8911
}
8912
#endif
8913
8914
void Assembler::subhnb(const ZRegister& zd,
8915
const ZRegister& zn,
8916
const ZRegister& zm) {
8917
// SUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8918
// 0100 0101 ..1. .... 0111 00.. .... ....
8919
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
8920
8921
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8922
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8923
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
8924
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
8925
8926
Emit(0x45207000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
8927
}
8928
8929
void Assembler::subhnt(const ZRegister& zd,
8930
const ZRegister& zn,
8931
const ZRegister& zm) {
8932
// SUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
8933
// 0100 0101 ..1. .... 0111 01.. .... ....
8934
// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>
8935
8936
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8937
VIXL_ASSERT(AreSameLaneSize(zn, zm));
8938
VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));
8939
VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);
8940
8941
Emit(0x45207400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));
8942
}
8943
8944
void Assembler::suqadd(const ZRegister& zd,
8945
const PRegisterM& pg,
8946
const ZRegister& zn,
8947
const ZRegister& zm) {
8948
// SUQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
8949
// 0100 0100 ..01 1100 100. .... .... ....
8950
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
8951
8952
USE(zn);
8953
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8954
VIXL_ASSERT(zd.Is(zn));
8955
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8956
8957
Emit(0x441c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
8958
}
8959
8960
void Assembler::tbl(const ZRegister& zd,
8961
const ZRegister& zn1,
8962
const ZRegister& zn2,
8963
const ZRegister& zm) {
8964
// TBL <Zd>.<T>, { <Zn1>.<T>, <Zn2>.<T> }, <Zm>.<T>
8965
// 0000 0101 ..1. .... 0010 10.. .... ....
8966
// size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>
8967
8968
USE(zn2);
8969
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8970
VIXL_ASSERT(AreConsecutive(zn1, zn2));
8971
VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2, zm));
8972
8973
Emit(0x05202800 | SVESize(zd) | Rd(zd) | Rn(zn1) | Rn(zn2) | Rm(zm));
8974
}
8975
8976
void Assembler::tbx(const ZRegister& zd,
8977
const ZRegister& zn,
8978
const ZRegister& zm) {
8979
// TBX <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
8980
// 0000 0101 ..1. .... 0010 11.. .... ....
8981
// size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>
8982
8983
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8984
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
8985
8986
Emit(0x05202c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
8987
}
8988
8989
void Assembler::uaba(const ZRegister& zda,
8990
const ZRegister& zn,
8991
const ZRegister& zm) {
8992
// UABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>
8993
// 0100 0101 ..0. .... 1111 11.. .... ....
8994
// size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>
8995
8996
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
8997
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
8998
8999
Emit(0x4500fc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9000
}
9001
9002
void Assembler::uabalb(const ZRegister& zda,
9003
const ZRegister& zn,
9004
const ZRegister& zm) {
9005
// UABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9006
// 0100 0101 ..0. .... 1100 10.. .... ....
9007
// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9008
9009
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9010
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9011
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9012
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9013
9014
Emit(0x4500c800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9015
}
9016
9017
void Assembler::uabalt(const ZRegister& zda,
9018
const ZRegister& zn,
9019
const ZRegister& zm) {
9020
// UABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9021
// 0100 0101 ..0. .... 1100 11.. .... ....
9022
// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9023
9024
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9025
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9026
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9027
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9028
9029
Emit(0x4500cc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9030
}
9031
9032
void Assembler::uabdlb(const ZRegister& zd,
9033
const ZRegister& zn,
9034
const ZRegister& zm) {
9035
// UABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9036
// 0100 0101 ..0. .... 0011 10.. .... ....
9037
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9038
// Zd<4:0>
9039
9040
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9041
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9042
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9043
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9044
9045
Emit(0x45003800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9046
}
9047
9048
void Assembler::uabdlt(const ZRegister& zd,
9049
const ZRegister& zn,
9050
const ZRegister& zm) {
9051
// UABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9052
// 0100 0101 ..0. .... 0011 11.. .... ....
9053
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9054
// Zd<4:0>
9055
9056
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9057
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9058
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9059
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9060
9061
Emit(0x45003c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9062
}
9063
9064
void Assembler::uadalp(const ZRegister& zda,
9065
const PRegisterM& pg,
9066
const ZRegister& zn) {
9067
// UADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>
9068
// 0100 0100 ..00 0101 101. .... .... ....
9069
// size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>
9070
9071
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9072
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9073
VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);
9074
9075
Emit(0x4405a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));
9076
}
9077
9078
void Assembler::uaddlb(const ZRegister& zd,
9079
const ZRegister& zn,
9080
const ZRegister& zm) {
9081
// UADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9082
// 0100 0101 ..0. .... 0000 10.. .... ....
9083
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9084
// Zd<4:0>
9085
9086
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9087
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9088
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9089
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9090
9091
Emit(0x45000800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9092
}
9093
9094
void Assembler::uaddlt(const ZRegister& zd,
9095
const ZRegister& zn,
9096
const ZRegister& zm) {
9097
// UADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9098
// 0100 0101 ..0. .... 0000 11.. .... ....
9099
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9100
// Zd<4:0>
9101
9102
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9103
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9104
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9105
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9106
9107
Emit(0x45000c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9108
}
9109
9110
void Assembler::uaddwb(const ZRegister& zd,
9111
const ZRegister& zn,
9112
const ZRegister& zm) {
9113
// UADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9114
// 0100 0101 ..0. .... 0100 10.. .... ....
9115
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9116
9117
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9118
VIXL_ASSERT(AreSameLaneSize(zd, zn));
9119
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9120
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9121
9122
Emit(0x45004800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9123
}
9124
9125
void Assembler::uaddwt(const ZRegister& zd,
9126
const ZRegister& zn,
9127
const ZRegister& zm) {
9128
// UADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9129
// 0100 0101 ..0. .... 0100 11.. .... ....
9130
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9131
9132
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9133
VIXL_ASSERT(AreSameLaneSize(zd, zn));
9134
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9135
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9136
9137
Emit(0x45004c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9138
}
9139
9140
void Assembler::uhadd(const ZRegister& zd,
9141
const PRegisterM& pg,
9142
const ZRegister& zn,
9143
const ZRegister& zm) {
9144
// UHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9145
// 0100 0100 ..01 0001 100. .... .... ....
9146
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9147
9148
USE(zn);
9149
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9150
VIXL_ASSERT(zd.Is(zn));
9151
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9152
9153
Emit(0x44118000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9154
}
9155
9156
void Assembler::uhsub(const ZRegister& zd,
9157
const PRegisterM& pg,
9158
const ZRegister& zn,
9159
const ZRegister& zm) {
9160
// UHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9161
// 0100 0100 ..01 0011 100. .... .... ....
9162
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9163
9164
USE(zn);
9165
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9166
VIXL_ASSERT(zd.Is(zn));
9167
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9168
9169
Emit(0x44138000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9170
}
9171
9172
void Assembler::uhsubr(const ZRegister& zd,
9173
const PRegisterM& pg,
9174
const ZRegister& zn,
9175
const ZRegister& zm) {
9176
// UHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9177
// 0100 0100 ..01 0111 100. .... .... ....
9178
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9179
9180
USE(zn);
9181
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9182
VIXL_ASSERT(zd.Is(zn));
9183
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9184
9185
Emit(0x44178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9186
}
9187
9188
void Assembler::umaxp(const ZRegister& zd,
9189
const PRegisterM& pg,
9190
const ZRegister& zn,
9191
const ZRegister& zm) {
9192
// UMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9193
// 0100 0100 ..01 0101 101. .... .... ....
9194
// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9195
9196
USE(zn);
9197
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9198
VIXL_ASSERT(zd.Is(zn));
9199
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9200
9201
Emit(0x4415a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9202
}
9203
9204
void Assembler::uminp(const ZRegister& zd,
9205
const PRegisterM& pg,
9206
const ZRegister& zn,
9207
const ZRegister& zm) {
9208
// UMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9209
// 0100 0100 ..01 0111 101. .... .... ....
9210
// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9211
9212
USE(zn);
9213
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9214
VIXL_ASSERT(zd.Is(zn));
9215
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9216
9217
Emit(0x4417a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9218
}
9219
9220
void Assembler::umlalb(const ZRegister& zda,
9221
const ZRegister& zn,
9222
const ZRegister& zm) {
9223
// UMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9224
// 0100 0100 ..0. .... 0100 10.. .... ....
9225
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9226
9227
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9228
VIXL_ASSERT(!zda.IsLaneSizeB());
9229
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9230
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9231
9232
Emit(0x44004800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9233
}
9234
9235
void Assembler::umlalt(const ZRegister& zda,
9236
const ZRegister& zn,
9237
const ZRegister& zm) {
9238
// UMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9239
// 0100 0100 ..0. .... 0100 11.. .... ....
9240
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9241
9242
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9243
VIXL_ASSERT(!zda.IsLaneSizeB());
9244
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9245
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9246
9247
Emit(0x44004c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9248
}
9249
9250
void Assembler::umlslb(const ZRegister& zda,
9251
const ZRegister& zn,
9252
const ZRegister& zm) {
9253
// UMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9254
// 0100 0100 ..0. .... 0101 10.. .... ....
9255
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9256
9257
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9258
VIXL_ASSERT(!zda.IsLaneSizeB());
9259
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9260
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9261
9262
Emit(0x44005800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9263
}
9264
9265
void Assembler::umlslt(const ZRegister& zda,
9266
const ZRegister& zn,
9267
const ZRegister& zm) {
9268
// UMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9269
// 0100 0100 ..0. .... 0101 11.. .... ....
9270
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>
9271
9272
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9273
VIXL_ASSERT(!zda.IsLaneSizeB());
9274
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9275
VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9276
9277
Emit(0x44005c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9278
}
9279
9280
void Assembler::umulh(const ZRegister& zd,
9281
const ZRegister& zn,
9282
const ZRegister& zm) {
9283
// UMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>
9284
// 0000 0100 ..1. .... 0110 11.. .... ....
9285
// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>
9286
9287
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9288
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9289
9290
Emit(0x04206c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9291
}
9292
9293
void Assembler::umullb(const ZRegister& zd,
9294
const ZRegister& zn,
9295
const ZRegister& zm) {
9296
// UMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9297
// 0100 0101 ..0. .... 0111 10.. .... ....
9298
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9299
9300
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9301
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9302
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
9303
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
9304
9305
Emit(0x45007800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9306
}
9307
9308
void Assembler::umullt(const ZRegister& zd,
9309
const ZRegister& zn,
9310
const ZRegister& zm) {
9311
// UMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9312
// 0100 0101 ..0. .... 0111 11.. .... ....
9313
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9314
9315
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9316
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9317
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());
9318
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
9319
9320
Emit(0x45007c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9321
}
9322
9323
void Assembler::uqadd(const ZRegister& zd,
9324
const PRegisterM& pg,
9325
const ZRegister& zn,
9326
const ZRegister& zm) {
9327
// UQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9328
// 0100 0100 ..01 1001 100. .... .... ....
9329
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9330
9331
USE(zn);
9332
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9333
VIXL_ASSERT(zd.Is(zn));
9334
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9335
9336
Emit(0x44198000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9337
}
9338
9339
void Assembler::uqrshl(const ZRegister& zd,
9340
const PRegisterM& pg,
9341
const ZRegister& zn,
9342
const ZRegister& zm) {
9343
// UQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9344
// 0100 0100 ..00 1011 100. .... .... ....
9345
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9346
// Zdn<4:0>
9347
9348
USE(zn);
9349
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9350
VIXL_ASSERT(zd.Is(zn));
9351
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9352
9353
Emit(0x440b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9354
}
9355
9356
void Assembler::uqrshlr(const ZRegister& zd,
9357
const PRegisterM& pg,
9358
const ZRegister& zn,
9359
const ZRegister& zm) {
9360
// UQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9361
// 0100 0100 ..00 1111 100. .... .... ....
9362
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9363
// Zdn<4:0>
9364
9365
USE(zn);
9366
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9367
VIXL_ASSERT(zd.Is(zn));
9368
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9369
9370
Emit(0x440f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9371
}
9372
9373
void Assembler::uqshl(const ZRegister& zd,
9374
const PRegisterM& pg,
9375
const ZRegister& zn,
9376
int shift) {
9377
// UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
9378
// 0000 0100 ..00 0111 100. .... .... ....
9379
// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
9380
// imm3<7:5> | Zdn<4:0>
9381
9382
USE(zn);
9383
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9384
VIXL_ASSERT(zd.Is(zn));
9385
Instr encoded_imm =
9386
EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());
9387
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04078000);
9388
}
9389
9390
void Assembler::uqshl(const ZRegister& zd,
9391
const PRegisterM& pg,
9392
const ZRegister& zn,
9393
const ZRegister& zm) {
9394
// UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9395
// 0100 0100 ..00 1001 100. .... .... ....
9396
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9397
// Zdn<4:0>
9398
9399
USE(zn);
9400
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9401
VIXL_ASSERT(zd.Is(zn));
9402
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9403
9404
Emit(0x44098000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9405
}
9406
9407
void Assembler::uqshlr(const ZRegister& zd,
9408
const PRegisterM& pg,
9409
const ZRegister& zn,
9410
const ZRegister& zm) {
9411
// UQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9412
// 0100 0100 ..00 1101 100. .... .... ....
9413
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9414
// Zdn<4:0>
9415
9416
USE(zn);
9417
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9418
VIXL_ASSERT(zd.Is(zn));
9419
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9420
9421
Emit(0x440d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9422
}
9423
9424
void Assembler::uqsub(const ZRegister& zd,
9425
const PRegisterM& pg,
9426
const ZRegister& zn,
9427
const ZRegister& zm) {
9428
// UQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9429
// 0100 0100 ..01 1011 100. .... .... ....
9430
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9431
9432
USE(zn);
9433
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9434
VIXL_ASSERT(zd.Is(zn));
9435
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9436
9437
Emit(0x441b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9438
}
9439
9440
void Assembler::uqsubr(const ZRegister& zd,
9441
const PRegisterM& pg,
9442
const ZRegister& zn,
9443
const ZRegister& zm) {
9444
// UQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9445
// 0100 0100 ..01 1111 100. .... .... ....
9446
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9447
9448
USE(zn);
9449
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9450
VIXL_ASSERT(zd.Is(zn));
9451
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9452
9453
Emit(0x441f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9454
}
9455
9456
void Assembler::uqxtnb(const ZRegister& zd, const ZRegister& zn) {
9457
// UQXTNB <Zd>.<T>, <Zn>.<Tb>
9458
// 0100 0101 0.1. .000 0100 10.. .... ....
9459
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
9460
9461
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9462
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
9463
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
9464
9465
// XTN instructions look like immediate shifts with zero shift distance.
9466
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
9467
SVEBitwiseShiftImmediate(zd, zn, size, 0x45204800);
9468
}
9469
9470
void Assembler::uqxtnt(const ZRegister& zd, const ZRegister& zn) {
9471
// UQXTNT <Zd>.<T>, <Zn>.<Tb>
9472
// 0100 0101 0.1. .000 0100 11.. .... ....
9473
// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>
9474
9475
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9476
VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());
9477
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));
9478
9479
// XTN instructions look like immediate shifts with zero shift distance.
9480
Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());
9481
SVEBitwiseShiftImmediate(zd, zn, size, 0x45204c00);
9482
}
9483
9484
void Assembler::urecpe(const ZRegister& zd,
9485
const PRegisterM& pg,
9486
const ZRegister& zn) {
9487
// URECPE <Zd>.S, <Pg>/M, <Zn>.S
9488
// 0100 0100 ..00 0000 101. .... .... ....
9489
// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
9490
9491
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9492
VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());
9493
9494
Emit(0x4400a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
9495
}
9496
9497
void Assembler::urhadd(const ZRegister& zd,
9498
const PRegisterM& pg,
9499
const ZRegister& zn,
9500
const ZRegister& zm) {
9501
// URHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9502
// 0100 0100 ..01 0101 100. .... .... ....
9503
// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9504
9505
USE(zn);
9506
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9507
VIXL_ASSERT(zd.Is(zn));
9508
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9509
9510
Emit(0x44158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9511
}
9512
9513
void Assembler::urshl(const ZRegister& zd,
9514
const PRegisterM& pg,
9515
const ZRegister& zn,
9516
const ZRegister& zm) {
9517
// URSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9518
// 0100 0100 ..00 0011 100. .... .... ....
9519
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9520
// Zdn<4:0>
9521
9522
USE(zn);
9523
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9524
VIXL_ASSERT(zd.Is(zn));
9525
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9526
9527
Emit(0x44038000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9528
}
9529
9530
void Assembler::urshlr(const ZRegister& zd,
9531
const PRegisterM& pg,
9532
const ZRegister& zn,
9533
const ZRegister& zm) {
9534
// URSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9535
// 0100 0100 ..00 0111 100. .... .... ....
9536
// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |
9537
// Zdn<4:0>
9538
9539
USE(zn);
9540
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9541
VIXL_ASSERT(zd.Is(zn));
9542
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9543
9544
Emit(0x44078000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9545
}
9546
9547
void Assembler::urshr(const ZRegister& zd,
9548
const PRegisterM& pg,
9549
const ZRegister& zn,
9550
int shift) {
9551
// URSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>
9552
// 0000 0100 ..00 1101 100. .... .... ....
9553
// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |
9554
// imm3<7:5> | Zdn<4:0>
9555
9556
USE(zn);
9557
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9558
VIXL_ASSERT(zd.Is(zn));
9559
Instr encoded_imm =
9560
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
9561
SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040d8000);
9562
}
9563
9564
void Assembler::ursqrte(const ZRegister& zd,
9565
const PRegisterM& pg,
9566
const ZRegister& zn) {
9567
// URSQRTE <Zd>.S, <Pg>/M, <Zn>.S
9568
// 0100 0100 ..00 0001 101. .... .... ....
9569
// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>
9570
9571
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9572
VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());
9573
9574
Emit(0x4401a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));
9575
}
9576
9577
void Assembler::ursra(const ZRegister& zda, const ZRegister& zn, int shift) {
9578
// URSRA <Zda>.<T>, <Zn>.<T>, #<const>
9579
// 0100 0101 ..0. .... 1110 11.. .... ....
9580
// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
9581
// Zda<4:0>
9582
9583
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9584
VIXL_ASSERT(AreSameLaneSize(zda, zn));
9585
Instr encoded_imm =
9586
EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
9587
9588
SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500ec00);
9589
}
9590
9591
void Assembler::ushllb(const ZRegister& zd, const ZRegister& zn, int shift) {
9592
// USHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>
9593
// 0100 0101 0.0. .... 1010 10.. .... ....
9594
// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9595
9596
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9597
VIXL_ASSERT(!zd.IsLaneSizeB());
9598
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9599
9600
Instr encoded_imm =
9601
EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
9602
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a800);
9603
}
9604
9605
void Assembler::ushllt(const ZRegister& zd, const ZRegister& zn, int shift) {
9606
// USHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>
9607
// 0100 0101 0.0. .... 1010 11.. .... ....
9608
// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9609
9610
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9611
VIXL_ASSERT(!zd.IsLaneSizeB());
9612
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9613
9614
Instr encoded_imm =
9615
EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());
9616
SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500ac00);
9617
}
9618
9619
void Assembler::usqadd(const ZRegister& zd,
9620
const PRegisterM& pg,
9621
const ZRegister& zn,
9622
const ZRegister& zm) {
9623
// USQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>
9624
// 0100 0100 ..01 1101 100. .... .... ....
9625
// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>
9626
9627
USE(zn);
9628
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9629
VIXL_ASSERT(zd.Is(zn));
9630
VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
9631
9632
Emit(0x441d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));
9633
}
9634
9635
void Assembler::usra(const ZRegister& zda, const ZRegister& zn, int shift) {
9636
// USRA <Zda>.<T>, <Zn>.<T>, #<const>
9637
// 0100 0101 ..0. .... 1110 01.. .... ....
9638
// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |
9639
// Zda<4:0>
9640
9641
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9642
VIXL_ASSERT(AreSameLaneSize(zda, zn));
9643
Instr encoded_imm =
9644
EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());
9645
9646
SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e400);
9647
}
9648
9649
void Assembler::usublb(const ZRegister& zd,
9650
const ZRegister& zn,
9651
const ZRegister& zm) {
9652
// USUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9653
// 0100 0101 ..0. .... 0001 10.. .... ....
9654
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9655
// Zd<4:0>
9656
9657
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9658
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9659
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9660
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9661
9662
Emit(0x45001800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9663
}
9664
9665
void Assembler::usublt(const ZRegister& zd,
9666
const ZRegister& zn,
9667
const ZRegister& zm) {
9668
// USUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>
9669
// 0100 0101 ..0. .... 0001 11.. .... ....
9670
// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |
9671
// Zd<4:0>
9672
9673
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9674
VIXL_ASSERT(AreSameLaneSize(zn, zm));
9675
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));
9676
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9677
9678
Emit(0x45001c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9679
}
9680
9681
void Assembler::usubwb(const ZRegister& zd,
9682
const ZRegister& zn,
9683
const ZRegister& zm) {
9684
// USUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9685
// 0100 0101 ..0. .... 0101 10.. .... ....
9686
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9687
9688
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9689
VIXL_ASSERT(AreSameLaneSize(zd, zn));
9690
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9691
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9692
9693
Emit(0x45005800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9694
}
9695
9696
void Assembler::usubwt(const ZRegister& zd,
9697
const ZRegister& zn,
9698
const ZRegister& zm) {
9699
// USUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>
9700
// 0100 0101 ..0. .... 0101 11.. .... ....
9701
// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
9702
9703
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9704
VIXL_ASSERT(AreSameLaneSize(zd, zn));
9705
VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));
9706
VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);
9707
9708
Emit(0x45005c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
9709
}
9710
9711
void Assembler::whilege(const PRegisterWithLaneSize& pd,
9712
const Register& rn,
9713
const Register& rm) {
9714
// WHILEGE <Pd>.<T>, <R><n>, <R><m>
9715
// 0010 0101 ..1. .... 000. 00.. ...0 ....
9716
// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9717
// Pd<3:0>
9718
9719
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9720
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9721
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9722
9723
Emit(0x25200000 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9724
}
9725
9726
void Assembler::whilegt(const PRegisterWithLaneSize& pd,
9727
const Register& rn,
9728
const Register& rm) {
9729
// WHILEGT <Pd>.<T>, <R><n>, <R><m>
9730
// 0010 0101 ..1. .... 000. 00.. ...1 ....
9731
// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9732
// Pd<3:0>
9733
9734
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9735
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9736
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9737
9738
Emit(0x25200010 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9739
}
9740
9741
void Assembler::whilehi(const PRegisterWithLaneSize& pd,
9742
const Register& rn,
9743
const Register& rm) {
9744
// WHILEHI <Pd>.<T>, <R><n>, <R><m>
9745
// 0010 0101 ..1. .... 000. 10.. ...1 ....
9746
// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9747
// Pd<3:0>
9748
9749
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9750
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9751
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9752
9753
Emit(0x25200810 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9754
}
9755
9756
void Assembler::whilehs(const PRegisterWithLaneSize& pd,
9757
const Register& rn,
9758
const Register& rm) {
9759
// WHILEHS <Pd>.<T>, <R><n>, <R><m>
9760
// 0010 0101 ..1. .... 000. 10.. ...0 ....
9761
// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |
9762
// Pd<3:0>
9763
9764
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9765
VIXL_ASSERT(AreSameSizeAndType(rn, rm));
9766
const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;
9767
9768
Emit(0x25200800 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));
9769
}
9770
9771
void Assembler::whilerw(const PRegisterWithLaneSize& pd,
9772
const Register& rn,
9773
const Register& rm) {
9774
// WHILERW <Pd>.<T>, <Xn>, <Xm>
9775
// 0010 0101 ..1. .... 0011 00.. ...1 ....
9776
// size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>
9777
9778
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9779
VIXL_ASSERT(rn.IsX() && rm.IsX());
9780
9781
Emit(0x25203010 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));
9782
}
9783
9784
void Assembler::whilewr(const PRegisterWithLaneSize& pd,
9785
const Register& rn,
9786
const Register& rm) {
9787
// WHILEWR <Pd>.<T>, <Xn>, <Xm>
9788
// 0010 0101 ..1. .... 0011 00.. ...0 ....
9789
// size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>
9790
9791
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9792
VIXL_ASSERT(rn.IsX() && rm.IsX());
9793
9794
Emit(0x25203000 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));
9795
}
9796
9797
void Assembler::xar(const ZRegister& zd,
9798
const ZRegister& zn,
9799
const ZRegister& zm,
9800
int shift) {
9801
// XAR <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<const>
9802
// 0000 0100 ..1. .... 0011 01.. .... ....
9803
// tszh<23:22> | tszl<20:19> | imm3<18:16> | Zm<9:5> | Zdn<4:0>
9804
9805
USE(zn);
9806
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
9807
VIXL_ASSERT(zd.Is(zn));
9808
VIXL_ASSERT(AreSameLaneSize(zd, zm));
9809
9810
Instr encoded_imm =
9811
EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());
9812
SVEBitwiseShiftImmediate(zd, zm, encoded_imm, 0x04203400);
9813
}
9814
9815
void Assembler::fmmla(const ZRegister& zda,
9816
const ZRegister& zn,
9817
const ZRegister& zm) {
9818
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9819
VIXL_ASSERT((CPUHas(CPUFeatures::kSVEF32MM) && zda.IsLaneSizeS()) ||
9820
(CPUHas(CPUFeatures::kSVEF64MM) && zda.IsLaneSizeD()));
9821
VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));
9822
9823
Emit(0x6420e400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));
9824
}
9825
9826
void Assembler::smmla(const ZRegister& zda,
9827
const ZRegister& zn,
9828
const ZRegister& zm) {
9829
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9830
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9831
VIXL_ASSERT(zda.IsLaneSizeS());
9832
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9833
9834
Emit(0x45009800 | Rd(zda) | Rn(zn) | Rm(zm));
9835
}
9836
9837
void Assembler::usmmla(const ZRegister& zda,
9838
const ZRegister& zn,
9839
const ZRegister& zm) {
9840
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9841
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9842
VIXL_ASSERT(zda.IsLaneSizeS());
9843
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9844
9845
Emit(0x45809800 | Rd(zda) | Rn(zn) | Rm(zm));
9846
}
9847
9848
void Assembler::ummla(const ZRegister& zda,
9849
const ZRegister& zn,
9850
const ZRegister& zm) {
9851
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9852
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9853
VIXL_ASSERT(zda.IsLaneSizeS());
9854
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9855
9856
Emit(0x45c09800 | Rd(zda) | Rn(zn) | Rm(zm));
9857
}
9858
9859
void Assembler::usdot(const ZRegister& zda,
9860
const ZRegister& zn,
9861
const ZRegister& zm) {
9862
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9863
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9864
VIXL_ASSERT(zda.IsLaneSizeS());
9865
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9866
9867
Emit(0x44807800 | Rd(zda) | Rn(zn) | Rm(zm));
9868
}
9869
9870
void Assembler::usdot(const ZRegister& zda,
9871
const ZRegister& zn,
9872
const ZRegister& zm,
9873
int index) {
9874
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9875
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9876
VIXL_ASSERT(zda.IsLaneSizeS());
9877
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9878
VIXL_ASSERT(zm.GetCode() <= 7);
9879
VIXL_ASSERT(IsUint2(index));
9880
9881
Emit(0x44a01800 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));
9882
}
9883
9884
void Assembler::sudot(const ZRegister& zda,
9885
const ZRegister& zn,
9886
const ZRegister& zm,
9887
int index) {
9888
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
9889
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));
9890
VIXL_ASSERT(zda.IsLaneSizeS());
9891
VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());
9892
VIXL_ASSERT(zm.GetCode() <= 7);
9893
VIXL_ASSERT(IsUint2(index));
9894
9895
Emit(0x44a01c00 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));
9896
}
9897
9898
} // namespace aarch64
9899
} // namespace vixl
9900
9901