1 // Copyright 2015, ARM Limited
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 #ifdef JS_SIMULATOR_ARM64
28
29 #include <cmath>
30
31 #include "jit/arm64/vixl/Simulator-vixl.h"
32
33 namespace vixl {
34
FPDefaultNaN()35 template<> double Simulator::FPDefaultNaN<double>() {
36 return kFP64DefaultNaN;
37 }
38
39
FPDefaultNaN()40 template<> float Simulator::FPDefaultNaN<float>() {
41 return kFP32DefaultNaN;
42 }
43
44
FixedToDouble(int64_t src,int fbits,FPRounding round)45 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
46 if (src >= 0) {
47 return UFixedToDouble(src, fbits, round);
48 } else {
49 // This works for all negative values, including INT64_MIN.
50 return -UFixedToDouble(-src, fbits, round);
51 }
52 }
53
54
UFixedToDouble(uint64_t src,int fbits,FPRounding round)55 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
56 // An input of 0 is a special case because the result is effectively
57 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
58 if (src == 0) {
59 return 0.0;
60 }
61
62 // Calculate the exponent. The highest significant bit will have the value
63 // 2^exponent.
64 const int highest_significant_bit = 63 - CountLeadingZeros(src);
65 const int64_t exponent = highest_significant_bit - fbits;
66
67 return FPRoundToDouble(0, exponent, src, round);
68 }
69
70
FixedToFloat(int64_t src,int fbits,FPRounding round)71 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
72 if (src >= 0) {
73 return UFixedToFloat(src, fbits, round);
74 } else {
75 // This works for all negative values, including INT64_MIN.
76 return -UFixedToFloat(-src, fbits, round);
77 }
78 }
79
80
UFixedToFloat(uint64_t src,int fbits,FPRounding round)81 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
82 // An input of 0 is a special case because the result is effectively
83 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
84 if (src == 0) {
85 return 0.0f;
86 }
87
88 // Calculate the exponent. The highest significant bit will have the value
89 // 2^exponent.
90 const int highest_significant_bit = 63 - CountLeadingZeros(src);
91 const int32_t exponent = highest_significant_bit - fbits;
92
93 return FPRoundToFloat(0, exponent, src, round);
94 }
95
96
ld1(VectorFormat vform,LogicVRegister dst,uint64_t addr)97 void Simulator::ld1(VectorFormat vform,
98 LogicVRegister dst,
99 uint64_t addr) {
100 if (handle_wasm_seg_fault(addr, 16))
101 return;
102 dst.ClearForWrite(vform);
103 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
104 dst.ReadUintFromMem(vform, i, addr);
105 addr += LaneSizeInBytesFromFormat(vform);
106 }
107 }
108
109
ld1(VectorFormat vform,LogicVRegister dst,int index,uint64_t addr)110 void Simulator::ld1(VectorFormat vform,
111 LogicVRegister dst,
112 int index,
113 uint64_t addr) {
114 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
115 return;
116 dst.ReadUintFromMem(vform, index, addr);
117 }
118
119
ld1r(VectorFormat vform,LogicVRegister dst,uint64_t addr)120 void Simulator::ld1r(VectorFormat vform,
121 LogicVRegister dst,
122 uint64_t addr) {
123 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
124 return;
125 dst.ClearForWrite(vform);
126 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
127 dst.ReadUintFromMem(vform, i, addr);
128 }
129 }
130
131
ld2(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,uint64_t addr1)132 void Simulator::ld2(VectorFormat vform,
133 LogicVRegister dst1,
134 LogicVRegister dst2,
135 uint64_t addr1) {
136 if (handle_wasm_seg_fault(addr1, 16*2))
137 return;
138 dst1.ClearForWrite(vform);
139 dst2.ClearForWrite(vform);
140 int esize = LaneSizeInBytesFromFormat(vform);
141 uint64_t addr2 = addr1 + esize;
142 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
143 dst1.ReadUintFromMem(vform, i, addr1);
144 dst2.ReadUintFromMem(vform, i, addr2);
145 addr1 += 2 * esize;
146 addr2 += 2 * esize;
147 }
148 }
149
150
ld2(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,int index,uint64_t addr1)151 void Simulator::ld2(VectorFormat vform,
152 LogicVRegister dst1,
153 LogicVRegister dst2,
154 int index,
155 uint64_t addr1) {
156 if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*2))
157 return;
158 dst1.ClearForWrite(vform);
159 dst2.ClearForWrite(vform);
160 uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform);
161 dst1.ReadUintFromMem(vform, index, addr1);
162 dst2.ReadUintFromMem(vform, index, addr2);
163 }
164
165
ld2r(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,uint64_t addr)166 void Simulator::ld2r(VectorFormat vform,
167 LogicVRegister dst1,
168 LogicVRegister dst2,
169 uint64_t addr) {
170 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*2))
171 return;
172 dst1.ClearForWrite(vform);
173 dst2.ClearForWrite(vform);
174 uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform);
175 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
176 dst1.ReadUintFromMem(vform, i, addr);
177 dst2.ReadUintFromMem(vform, i, addr2);
178 }
179 }
180
181
ld3(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,uint64_t addr1)182 void Simulator::ld3(VectorFormat vform,
183 LogicVRegister dst1,
184 LogicVRegister dst2,
185 LogicVRegister dst3,
186 uint64_t addr1) {
187 if (handle_wasm_seg_fault(addr1, 16*3))
188 return;
189 dst1.ClearForWrite(vform);
190 dst2.ClearForWrite(vform);
191 dst3.ClearForWrite(vform);
192 int esize = LaneSizeInBytesFromFormat(vform);
193 uint64_t addr2 = addr1 + esize;
194 uint64_t addr3 = addr2 + esize;
195 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
196 dst1.ReadUintFromMem(vform, i, addr1);
197 dst2.ReadUintFromMem(vform, i, addr2);
198 dst3.ReadUintFromMem(vform, i, addr3);
199 addr1 += 3 * esize;
200 addr2 += 3 * esize;
201 addr3 += 3 * esize;
202 }
203 }
204
205
ld3(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,int index,uint64_t addr1)206 void Simulator::ld3(VectorFormat vform,
207 LogicVRegister dst1,
208 LogicVRegister dst2,
209 LogicVRegister dst3,
210 int index,
211 uint64_t addr1) {
212 if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*3))
213 return;
214 dst1.ClearForWrite(vform);
215 dst2.ClearForWrite(vform);
216 dst3.ClearForWrite(vform);
217 uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform);
218 uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform);
219 dst1.ReadUintFromMem(vform, index, addr1);
220 dst2.ReadUintFromMem(vform, index, addr2);
221 dst3.ReadUintFromMem(vform, index, addr3);
222 }
223
224
ld3r(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,uint64_t addr)225 void Simulator::ld3r(VectorFormat vform,
226 LogicVRegister dst1,
227 LogicVRegister dst2,
228 LogicVRegister dst3,
229 uint64_t addr) {
230 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*3))
231 return;
232 dst1.ClearForWrite(vform);
233 dst2.ClearForWrite(vform);
234 dst3.ClearForWrite(vform);
235 uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform);
236 uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform);
237 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
238 dst1.ReadUintFromMem(vform, i, addr);
239 dst2.ReadUintFromMem(vform, i, addr2);
240 dst3.ReadUintFromMem(vform, i, addr3);
241 }
242 }
243
244
ld4(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,LogicVRegister dst4,uint64_t addr1)245 void Simulator::ld4(VectorFormat vform,
246 LogicVRegister dst1,
247 LogicVRegister dst2,
248 LogicVRegister dst3,
249 LogicVRegister dst4,
250 uint64_t addr1) {
251 if (handle_wasm_seg_fault(addr1, 16*4))
252 return;
253 dst1.ClearForWrite(vform);
254 dst2.ClearForWrite(vform);
255 dst3.ClearForWrite(vform);
256 dst4.ClearForWrite(vform);
257 int esize = LaneSizeInBytesFromFormat(vform);
258 uint64_t addr2 = addr1 + esize;
259 uint64_t addr3 = addr2 + esize;
260 uint64_t addr4 = addr3 + esize;
261 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
262 dst1.ReadUintFromMem(vform, i, addr1);
263 dst2.ReadUintFromMem(vform, i, addr2);
264 dst3.ReadUintFromMem(vform, i, addr3);
265 dst4.ReadUintFromMem(vform, i, addr4);
266 addr1 += 4 * esize;
267 addr2 += 4 * esize;
268 addr3 += 4 * esize;
269 addr4 += 4 * esize;
270 }
271 }
272
273
ld4(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,LogicVRegister dst4,int index,uint64_t addr1)274 void Simulator::ld4(VectorFormat vform,
275 LogicVRegister dst1,
276 LogicVRegister dst2,
277 LogicVRegister dst3,
278 LogicVRegister dst4,
279 int index,
280 uint64_t addr1) {
281 if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*4))
282 return;
283 dst1.ClearForWrite(vform);
284 dst2.ClearForWrite(vform);
285 dst3.ClearForWrite(vform);
286 dst4.ClearForWrite(vform);
287 uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform);
288 uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform);
289 uint64_t addr4 = addr3 + LaneSizeInBytesFromFormat(vform);
290 dst1.ReadUintFromMem(vform, index, addr1);
291 dst2.ReadUintFromMem(vform, index, addr2);
292 dst3.ReadUintFromMem(vform, index, addr3);
293 dst4.ReadUintFromMem(vform, index, addr4);
294 }
295
296
ld4r(VectorFormat vform,LogicVRegister dst1,LogicVRegister dst2,LogicVRegister dst3,LogicVRegister dst4,uint64_t addr)297 void Simulator::ld4r(VectorFormat vform,
298 LogicVRegister dst1,
299 LogicVRegister dst2,
300 LogicVRegister dst3,
301 LogicVRegister dst4,
302 uint64_t addr) {
303 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*4))
304 return;
305 dst1.ClearForWrite(vform);
306 dst2.ClearForWrite(vform);
307 dst3.ClearForWrite(vform);
308 dst4.ClearForWrite(vform);
309 uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform);
310 uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform);
311 uint64_t addr4 = addr3 + LaneSizeInBytesFromFormat(vform);
312 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
313 dst1.ReadUintFromMem(vform, i, addr);
314 dst2.ReadUintFromMem(vform, i, addr2);
315 dst3.ReadUintFromMem(vform, i, addr3);
316 dst4.ReadUintFromMem(vform, i, addr4);
317 }
318 }
319
320
st1(VectorFormat vform,LogicVRegister src,uint64_t addr)321 void Simulator::st1(VectorFormat vform,
322 LogicVRegister src,
323 uint64_t addr) {
324 if (handle_wasm_seg_fault(addr, 16))
325 return;
326 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
327 src.WriteUintToMem(vform, i, addr);
328 addr += LaneSizeInBytesFromFormat(vform);
329 }
330 }
331
332
st1(VectorFormat vform,LogicVRegister src,int index,uint64_t addr)333 void Simulator::st1(VectorFormat vform,
334 LogicVRegister src,
335 int index,
336 uint64_t addr) {
337 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
338 return;
339 src.WriteUintToMem(vform, index, addr);
340 }
341
342
st2(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,uint64_t addr)343 void Simulator::st2(VectorFormat vform,
344 LogicVRegister dst,
345 LogicVRegister dst2,
346 uint64_t addr) {
347 if (handle_wasm_seg_fault(addr, 16*2))
348 return;
349 int esize = LaneSizeInBytesFromFormat(vform);
350 uint64_t addr2 = addr + esize;
351 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
352 dst.WriteUintToMem(vform, i, addr);
353 dst2.WriteUintToMem(vform, i, addr2);
354 addr += 2 * esize;
355 addr2 += 2 * esize;
356 }
357 }
358
359
st2(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,int index,uint64_t addr)360 void Simulator::st2(VectorFormat vform,
361 LogicVRegister dst,
362 LogicVRegister dst2,
363 int index,
364 uint64_t addr) {
365 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*2))
366 return;
367 int esize = LaneSizeInBytesFromFormat(vform);
368 dst.WriteUintToMem(vform, index, addr);
369 dst2.WriteUintToMem(vform, index, addr + 1 * esize);
370 }
371
372
st3(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,LogicVRegister dst3,uint64_t addr)373 void Simulator::st3(VectorFormat vform,
374 LogicVRegister dst,
375 LogicVRegister dst2,
376 LogicVRegister dst3,
377 uint64_t addr) {
378 if (handle_wasm_seg_fault(addr, 16*3))
379 return;
380 int esize = LaneSizeInBytesFromFormat(vform);
381 uint64_t addr2 = addr + esize;
382 uint64_t addr3 = addr2 + esize;
383 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
384 dst.WriteUintToMem(vform, i, addr);
385 dst2.WriteUintToMem(vform, i, addr2);
386 dst3.WriteUintToMem(vform, i, addr3);
387 addr += 3 * esize;
388 addr2 += 3 * esize;
389 addr3 += 3 * esize;
390 }
391 }
392
393
st3(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,LogicVRegister dst3,int index,uint64_t addr)394 void Simulator::st3(VectorFormat vform,
395 LogicVRegister dst,
396 LogicVRegister dst2,
397 LogicVRegister dst3,
398 int index,
399 uint64_t addr) {
400 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*3))
401 return;
402 int esize = LaneSizeInBytesFromFormat(vform);
403 dst.WriteUintToMem(vform, index, addr);
404 dst2.WriteUintToMem(vform, index, addr + 1 * esize);
405 dst3.WriteUintToMem(vform, index, addr + 2 * esize);
406 }
407
408
st4(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,LogicVRegister dst3,LogicVRegister dst4,uint64_t addr)409 void Simulator::st4(VectorFormat vform,
410 LogicVRegister dst,
411 LogicVRegister dst2,
412 LogicVRegister dst3,
413 LogicVRegister dst4,
414 uint64_t addr) {
415 if (handle_wasm_seg_fault(addr, 16*4))
416 return;
417 int esize = LaneSizeInBytesFromFormat(vform);
418 uint64_t addr2 = addr + esize;
419 uint64_t addr3 = addr2 + esize;
420 uint64_t addr4 = addr3 + esize;
421 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
422 dst.WriteUintToMem(vform, i, addr);
423 dst2.WriteUintToMem(vform, i, addr2);
424 dst3.WriteUintToMem(vform, i, addr3);
425 dst4.WriteUintToMem(vform, i, addr4);
426 addr += 4 * esize;
427 addr2 += 4 * esize;
428 addr3 += 4 * esize;
429 addr4 += 4 * esize;
430 }
431 }
432
433
st4(VectorFormat vform,LogicVRegister dst,LogicVRegister dst2,LogicVRegister dst3,LogicVRegister dst4,int index,uint64_t addr)434 void Simulator::st4(VectorFormat vform,
435 LogicVRegister dst,
436 LogicVRegister dst2,
437 LogicVRegister dst3,
438 LogicVRegister dst4,
439 int index,
440 uint64_t addr) {
441 if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*4))
442 return;
443 int esize = LaneSizeInBytesFromFormat(vform);
444 dst.WriteUintToMem(vform, index, addr);
445 dst2.WriteUintToMem(vform, index, addr + 1 * esize);
446 dst3.WriteUintToMem(vform, index, addr + 2 * esize);
447 dst4.WriteUintToMem(vform, index, addr + 3 * esize);
448 }
449
450
cmp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,Condition cond)451 LogicVRegister Simulator::cmp(VectorFormat vform,
452 LogicVRegister dst,
453 const LogicVRegister& src1,
454 const LogicVRegister& src2,
455 Condition cond) {
456 dst.ClearForWrite(vform);
457 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
458 int64_t sa = src1.Int(vform, i);
459 int64_t sb = src2.Int(vform, i);
460 uint64_t ua = src1.Uint(vform, i);
461 uint64_t ub = src2.Uint(vform, i);
462 bool result = false;
463 switch (cond) {
464 case eq: result = (ua == ub); break;
465 case ge: result = (sa >= sb); break;
466 case gt: result = (sa > sb) ; break;
467 case hi: result = (ua > ub) ; break;
468 case hs: result = (ua >= ub); break;
469 case lt: result = (sa < sb) ; break;
470 case le: result = (sa <= sb); break;
471 default: VIXL_UNREACHABLE(); break;
472 }
473 dst.SetUint(vform, i, result ? MaxUintFromFormat(vform) : 0);
474 }
475 return dst;
476 }
477
478
cmp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,int imm,Condition cond)479 LogicVRegister Simulator::cmp(VectorFormat vform,
480 LogicVRegister dst,
481 const LogicVRegister& src1,
482 int imm,
483 Condition cond) {
484 SimVRegister temp;
485 LogicVRegister imm_reg = dup_immediate(vform, temp, imm);
486 return cmp(vform, dst, src1, imm_reg, cond);
487 }
488
489
cmptst(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)490 LogicVRegister Simulator::cmptst(VectorFormat vform,
491 LogicVRegister dst,
492 const LogicVRegister& src1,
493 const LogicVRegister& src2) {
494 dst.ClearForWrite(vform);
495 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
496 uint64_t ua = src1.Uint(vform, i);
497 uint64_t ub = src2.Uint(vform, i);
498 dst.SetUint(vform, i, ((ua & ub) != 0) ? MaxUintFromFormat(vform) : 0);
499 }
500 return dst;
501 }
502
503
add(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)504 LogicVRegister Simulator::add(VectorFormat vform,
505 LogicVRegister dst,
506 const LogicVRegister& src1,
507 const LogicVRegister& src2) {
508 dst.ClearForWrite(vform);
509 // TODO(all): consider assigning the result of LaneCountFromFormat to a local.
510 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
511 // Test for unsigned saturation.
512 uint64_t ua = src1.UintLeftJustified(vform, i);
513 uint64_t ub = src2.UintLeftJustified(vform, i);
514 uint64_t ur = ua + ub;
515 if (ur < ua) {
516 dst.SetUnsignedSat(i, true);
517 }
518
519 // Test for signed saturation.
520 int64_t sa = src1.IntLeftJustified(vform, i);
521 int64_t sb = src2.IntLeftJustified(vform, i);
522 int64_t sr = sa + sb;
523 // If the signs of the operands are the same, but different from the result,
524 // there was an overflow.
525 if (((sa >= 0) == (sb >= 0)) && ((sa >= 0) != (sr >= 0))) {
526 dst.SetSignedSat(i, sa >= 0);
527 }
528
529 dst.SetInt(vform, i, src1.Int(vform, i) + src2.Int(vform, i));
530 }
531 return dst;
532 }
533
534
addp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)535 LogicVRegister Simulator::addp(VectorFormat vform,
536 LogicVRegister dst,
537 const LogicVRegister& src1,
538 const LogicVRegister& src2) {
539 SimVRegister temp1, temp2;
540 uzp1(vform, temp1, src1, src2);
541 uzp2(vform, temp2, src1, src2);
542 add(vform, dst, temp1, temp2);
543 return dst;
544 }
545
546
mla(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)547 LogicVRegister Simulator::mla(VectorFormat vform,
548 LogicVRegister dst,
549 const LogicVRegister& src1,
550 const LogicVRegister& src2) {
551 SimVRegister temp;
552 mul(vform, temp, src1, src2);
553 add(vform, dst, dst, temp);
554 return dst;
555 }
556
557
mls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)558 LogicVRegister Simulator::mls(VectorFormat vform,
559 LogicVRegister dst,
560 const LogicVRegister& src1,
561 const LogicVRegister& src2) {
562 SimVRegister temp;
563 mul(vform, temp, src1, src2);
564 sub(vform, dst, dst, temp);
565 return dst;
566 }
567
568
mul(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)569 LogicVRegister Simulator::mul(VectorFormat vform,
570 LogicVRegister dst,
571 const LogicVRegister& src1,
572 const LogicVRegister& src2) {
573 dst.ClearForWrite(vform);
574 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
575 dst.SetUint(vform, i, src1.Uint(vform, i) * src2.Uint(vform, i));
576 }
577 return dst;
578 }
579
580
mul(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)581 LogicVRegister Simulator::mul(VectorFormat vform,
582 LogicVRegister dst,
583 const LogicVRegister& src1,
584 const LogicVRegister& src2,
585 int index) {
586 SimVRegister temp;
587 VectorFormat indexform = VectorFormatFillQ(vform);
588 return mul(vform, dst, src1, dup_element(indexform, temp, src2, index));
589 }
590
591
mla(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)592 LogicVRegister Simulator::mla(VectorFormat vform,
593 LogicVRegister dst,
594 const LogicVRegister& src1,
595 const LogicVRegister& src2,
596 int index) {
597 SimVRegister temp;
598 VectorFormat indexform = VectorFormatFillQ(vform);
599 return mla(vform, dst, src1, dup_element(indexform, temp, src2, index));
600 }
601
602
mls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)603 LogicVRegister Simulator::mls(VectorFormat vform,
604 LogicVRegister dst,
605 const LogicVRegister& src1,
606 const LogicVRegister& src2,
607 int index) {
608 SimVRegister temp;
609 VectorFormat indexform = VectorFormatFillQ(vform);
610 return mls(vform, dst, src1, dup_element(indexform, temp, src2, index));
611 }
612
613
smull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)614 LogicVRegister Simulator::smull(VectorFormat vform,
615 LogicVRegister dst,
616 const LogicVRegister& src1,
617 const LogicVRegister& src2,
618 int index) {
619 SimVRegister temp;
620 VectorFormat indexform =
621 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
622 return smull(vform, dst, src1, dup_element(indexform, temp, src2, index));
623 }
624
625
smull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)626 LogicVRegister Simulator::smull2(VectorFormat vform,
627 LogicVRegister dst,
628 const LogicVRegister& src1,
629 const LogicVRegister& src2,
630 int index) {
631 SimVRegister temp;
632 VectorFormat indexform =
633 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
634 return smull2(vform, dst, src1, dup_element(indexform, temp, src2, index));
635 }
636
637
umull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)638 LogicVRegister Simulator::umull(VectorFormat vform,
639 LogicVRegister dst,
640 const LogicVRegister& src1,
641 const LogicVRegister& src2,
642 int index) {
643 SimVRegister temp;
644 VectorFormat indexform =
645 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
646 return umull(vform, dst, src1, dup_element(indexform, temp, src2, index));
647 }
648
649
umull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)650 LogicVRegister Simulator::umull2(VectorFormat vform,
651 LogicVRegister dst,
652 const LogicVRegister& src1,
653 const LogicVRegister& src2,
654 int index) {
655 SimVRegister temp;
656 VectorFormat indexform =
657 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
658 return umull2(vform, dst, src1, dup_element(indexform, temp, src2, index));
659 }
660
661
smlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)662 LogicVRegister Simulator::smlal(VectorFormat vform,
663 LogicVRegister dst,
664 const LogicVRegister& src1,
665 const LogicVRegister& src2,
666 int index) {
667 SimVRegister temp;
668 VectorFormat indexform =
669 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
670 return smlal(vform, dst, src1, dup_element(indexform, temp, src2, index));
671 }
672
673
smlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)674 LogicVRegister Simulator::smlal2(VectorFormat vform,
675 LogicVRegister dst,
676 const LogicVRegister& src1,
677 const LogicVRegister& src2,
678 int index) {
679 SimVRegister temp;
680 VectorFormat indexform =
681 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
682 return smlal2(vform, dst, src1, dup_element(indexform, temp, src2, index));
683 }
684
685
umlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)686 LogicVRegister Simulator::umlal(VectorFormat vform,
687 LogicVRegister dst,
688 const LogicVRegister& src1,
689 const LogicVRegister& src2,
690 int index) {
691 SimVRegister temp;
692 VectorFormat indexform =
693 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
694 return umlal(vform, dst, src1, dup_element(indexform, temp, src2, index));
695 }
696
697
umlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)698 LogicVRegister Simulator::umlal2(VectorFormat vform,
699 LogicVRegister dst,
700 const LogicVRegister& src1,
701 const LogicVRegister& src2,
702 int index) {
703 SimVRegister temp;
704 VectorFormat indexform =
705 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
706 return umlal2(vform, dst, src1, dup_element(indexform, temp, src2, index));
707 }
708
709
smlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)710 LogicVRegister Simulator::smlsl(VectorFormat vform,
711 LogicVRegister dst,
712 const LogicVRegister& src1,
713 const LogicVRegister& src2,
714 int index) {
715 SimVRegister temp;
716 VectorFormat indexform =
717 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
718 return smlsl(vform, dst, src1, dup_element(indexform, temp, src2, index));
719 }
720
721
smlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)722 LogicVRegister Simulator::smlsl2(VectorFormat vform,
723 LogicVRegister dst,
724 const LogicVRegister& src1,
725 const LogicVRegister& src2,
726 int index) {
727 SimVRegister temp;
728 VectorFormat indexform =
729 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
730 return smlsl2(vform, dst, src1, dup_element(indexform, temp, src2, index));
731 }
732
733
umlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)734 LogicVRegister Simulator::umlsl(VectorFormat vform,
735 LogicVRegister dst,
736 const LogicVRegister& src1,
737 const LogicVRegister& src2,
738 int index) {
739 SimVRegister temp;
740 VectorFormat indexform =
741 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
742 return umlsl(vform, dst, src1, dup_element(indexform, temp, src2, index));
743 }
744
745
umlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)746 LogicVRegister Simulator::umlsl2(VectorFormat vform,
747 LogicVRegister dst,
748 const LogicVRegister& src1,
749 const LogicVRegister& src2,
750 int index) {
751 SimVRegister temp;
752 VectorFormat indexform =
753 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
754 return umlsl2(vform, dst, src1, dup_element(indexform, temp, src2, index));
755 }
756
757
sqdmull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)758 LogicVRegister Simulator::sqdmull(VectorFormat vform,
759 LogicVRegister dst,
760 const LogicVRegister& src1,
761 const LogicVRegister& src2,
762 int index) {
763 SimVRegister temp;
764 VectorFormat indexform =
765 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
766 return sqdmull(vform, dst, src1, dup_element(indexform, temp, src2, index));
767 }
768
769
sqdmull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)770 LogicVRegister Simulator::sqdmull2(VectorFormat vform,
771 LogicVRegister dst,
772 const LogicVRegister& src1,
773 const LogicVRegister& src2,
774 int index) {
775 SimVRegister temp;
776 VectorFormat indexform =
777 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
778 return sqdmull2(vform, dst, src1, dup_element(indexform, temp, src2, index));
779 }
780
781
sqdmlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)782 LogicVRegister Simulator::sqdmlal(VectorFormat vform,
783 LogicVRegister dst,
784 const LogicVRegister& src1,
785 const LogicVRegister& src2,
786 int index) {
787 SimVRegister temp;
788 VectorFormat indexform =
789 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
790 return sqdmlal(vform, dst, src1, dup_element(indexform, temp, src2, index));
791 }
792
793
sqdmlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)794 LogicVRegister Simulator::sqdmlal2(VectorFormat vform,
795 LogicVRegister dst,
796 const LogicVRegister& src1,
797 const LogicVRegister& src2,
798 int index) {
799 SimVRegister temp;
800 VectorFormat indexform =
801 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
802 return sqdmlal2(vform, dst, src1, dup_element(indexform, temp, src2, index));
803 }
804
805
sqdmlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)806 LogicVRegister Simulator::sqdmlsl(VectorFormat vform,
807 LogicVRegister dst,
808 const LogicVRegister& src1,
809 const LogicVRegister& src2,
810 int index) {
811 SimVRegister temp;
812 VectorFormat indexform =
813 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
814 return sqdmlsl(vform, dst, src1, dup_element(indexform, temp, src2, index));
815 }
816
817
sqdmlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)818 LogicVRegister Simulator::sqdmlsl2(VectorFormat vform,
819 LogicVRegister dst,
820 const LogicVRegister& src1,
821 const LogicVRegister& src2,
822 int index) {
823 SimVRegister temp;
824 VectorFormat indexform =
825 VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vform));
826 return sqdmlsl2(vform, dst, src1, dup_element(indexform, temp, src2, index));
827 }
828
829
sqdmulh(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)830 LogicVRegister Simulator::sqdmulh(VectorFormat vform,
831 LogicVRegister dst,
832 const LogicVRegister& src1,
833 const LogicVRegister& src2,
834 int index) {
835 SimVRegister temp;
836 VectorFormat indexform = VectorFormatFillQ(vform);
837 return sqdmulh(vform, dst, src1, dup_element(indexform, temp, src2, index));
838 }
839
840
sqrdmulh(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)841 LogicVRegister Simulator::sqrdmulh(VectorFormat vform,
842 LogicVRegister dst,
843 const LogicVRegister& src1,
844 const LogicVRegister& src2,
845 int index) {
846 SimVRegister temp;
847 VectorFormat indexform = VectorFormatFillQ(vform);
848 return sqrdmulh(vform, dst, src1, dup_element(indexform, temp, src2, index));
849 }
850
851
PolynomialMult(uint8_t op1,uint8_t op2)852 uint16_t Simulator::PolynomialMult(uint8_t op1, uint8_t op2) {
853 uint16_t result = 0;
854 uint16_t extended_op2 = op2;
855 for (int i = 0; i < 8; ++i) {
856 if ((op1 >> i) & 1) {
857 result = result ^ (extended_op2 << i);
858 }
859 }
860 return result;
861 }
862
863
pmul(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)864 LogicVRegister Simulator::pmul(VectorFormat vform,
865 LogicVRegister dst,
866 const LogicVRegister& src1,
867 const LogicVRegister& src2) {
868 dst.ClearForWrite(vform);
869 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
870 dst.SetUint(vform, i,
871 PolynomialMult(src1.Uint(vform, i), src2.Uint(vform, i)));
872 }
873 return dst;
874 }
875
876
pmull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)877 LogicVRegister Simulator::pmull(VectorFormat vform,
878 LogicVRegister dst,
879 const LogicVRegister& src1,
880 const LogicVRegister& src2) {
881 VectorFormat vform_src = VectorFormatHalfWidth(vform);
882 dst.ClearForWrite(vform);
883 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
884 dst.SetUint(vform, i, PolynomialMult(src1.Uint(vform_src, i),
885 src2.Uint(vform_src, i)));
886 }
887 return dst;
888 }
889
890
pmull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)891 LogicVRegister Simulator::pmull2(VectorFormat vform,
892 LogicVRegister dst,
893 const LogicVRegister& src1,
894 const LogicVRegister& src2) {
895 VectorFormat vform_src = VectorFormatHalfWidthDoubleLanes(vform);
896 dst.ClearForWrite(vform);
897 int lane_count = LaneCountFromFormat(vform);
898 for (int i = 0; i < lane_count; i++) {
899 dst.SetUint(vform, i, PolynomialMult(src1.Uint(vform_src, lane_count + i),
900 src2.Uint(vform_src, lane_count + i)));
901 }
902 return dst;
903 }
904
905
sub(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)906 LogicVRegister Simulator::sub(VectorFormat vform,
907 LogicVRegister dst,
908 const LogicVRegister& src1,
909 const LogicVRegister& src2) {
910 dst.ClearForWrite(vform);
911 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
912 // Test for unsigned saturation.
913 if (src2.Uint(vform, i) > src1.Uint(vform, i)) {
914 dst.SetUnsignedSat(i, false);
915 }
916
917 // Test for signed saturation.
918 int64_t sa = src1.IntLeftJustified(vform, i);
919 int64_t sb = src2.IntLeftJustified(vform, i);
920 int64_t sr = sa - sb;
921 // If the signs of the operands are different, and the sign of the first
922 // operand doesn't match the result, there was an overflow.
923 if (((sa >= 0) != (sb >= 0)) && ((sa >= 0) != (sr >= 0))) {
924 dst.SetSignedSat(i, sr < 0);
925 }
926
927 dst.SetInt(vform, i, src1.Int(vform, i) - src2.Int(vform, i));
928 }
929 return dst;
930 }
931
932
and_(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)933 LogicVRegister Simulator::and_(VectorFormat vform,
934 LogicVRegister dst,
935 const LogicVRegister& src1,
936 const LogicVRegister& src2) {
937 dst.ClearForWrite(vform);
938 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
939 dst.SetUint(vform, i, src1.Uint(vform, i) & src2.Uint(vform, i));
940 }
941 return dst;
942 }
943
944
orr(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)945 LogicVRegister Simulator::orr(VectorFormat vform,
946 LogicVRegister dst,
947 const LogicVRegister& src1,
948 const LogicVRegister& src2) {
949 dst.ClearForWrite(vform);
950 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
951 dst.SetUint(vform, i, src1.Uint(vform, i) | src2.Uint(vform, i));
952 }
953 return dst;
954 }
955
956
orn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)957 LogicVRegister Simulator::orn(VectorFormat vform,
958 LogicVRegister dst,
959 const LogicVRegister& src1,
960 const LogicVRegister& src2) {
961 dst.ClearForWrite(vform);
962 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
963 dst.SetUint(vform, i, src1.Uint(vform, i) | ~src2.Uint(vform, i));
964 }
965 return dst;
966 }
967
968
eor(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)969 LogicVRegister Simulator::eor(VectorFormat vform,
970 LogicVRegister dst,
971 const LogicVRegister& src1,
972 const LogicVRegister& src2) {
973 dst.ClearForWrite(vform);
974 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
975 dst.SetUint(vform, i, src1.Uint(vform, i) ^ src2.Uint(vform, i));
976 }
977 return dst;
978 }
979
980
bic(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)981 LogicVRegister Simulator::bic(VectorFormat vform,
982 LogicVRegister dst,
983 const LogicVRegister& src1,
984 const LogicVRegister& src2) {
985 dst.ClearForWrite(vform);
986 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
987 dst.SetUint(vform, i, src1.Uint(vform, i) & ~src2.Uint(vform, i));
988 }
989 return dst;
990 }
991
992
bic(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,uint64_t imm)993 LogicVRegister Simulator::bic(VectorFormat vform,
994 LogicVRegister dst,
995 const LogicVRegister& src,
996 uint64_t imm) {
997 uint64_t result[16];
998 int laneCount = LaneCountFromFormat(vform);
999 for (int i = 0; i < laneCount; ++i) {
1000 result[i] = src.Uint(vform, i) & ~imm;
1001 }
1002 dst.ClearForWrite(vform);
1003 for (int i = 0; i < laneCount; ++i) {
1004 dst.SetUint(vform, i, result[i]);
1005 }
1006 return dst;
1007 }
1008
1009
bif(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1010 LogicVRegister Simulator::bif(VectorFormat vform,
1011 LogicVRegister dst,
1012 const LogicVRegister& src1,
1013 const LogicVRegister& src2) {
1014 dst.ClearForWrite(vform);
1015 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1016 uint64_t operand1 = dst.Uint(vform, i);
1017 uint64_t operand2 = ~src2.Uint(vform, i);
1018 uint64_t operand3 = src1.Uint(vform, i);
1019 uint64_t result = operand1 ^ ((operand1 ^ operand3) & operand2);
1020 dst.SetUint(vform, i, result);
1021 }
1022 return dst;
1023 }
1024
1025
bit(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1026 LogicVRegister Simulator::bit(VectorFormat vform,
1027 LogicVRegister dst,
1028 const LogicVRegister& src1,
1029 const LogicVRegister& src2) {
1030 dst.ClearForWrite(vform);
1031 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1032 uint64_t operand1 = dst.Uint(vform, i);
1033 uint64_t operand2 = src2.Uint(vform, i);
1034 uint64_t operand3 = src1.Uint(vform, i);
1035 uint64_t result = operand1 ^ ((operand1 ^ operand3) & operand2);
1036 dst.SetUint(vform, i, result);
1037 }
1038 return dst;
1039 }
1040
1041
bsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1042 LogicVRegister Simulator::bsl(VectorFormat vform,
1043 LogicVRegister dst,
1044 const LogicVRegister& src1,
1045 const LogicVRegister& src2) {
1046 dst.ClearForWrite(vform);
1047 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1048 uint64_t operand1 = src2.Uint(vform, i);
1049 uint64_t operand2 = dst.Uint(vform, i);
1050 uint64_t operand3 = src1.Uint(vform, i);
1051 uint64_t result = operand1 ^ ((operand1 ^ operand3) & operand2);
1052 dst.SetUint(vform, i, result);
1053 }
1054 return dst;
1055 }
1056
1057
sminmax(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,bool max)1058 LogicVRegister Simulator::sminmax(VectorFormat vform,
1059 LogicVRegister dst,
1060 const LogicVRegister& src1,
1061 const LogicVRegister& src2,
1062 bool max) {
1063 dst.ClearForWrite(vform);
1064 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1065 int64_t src1_val = src1.Int(vform, i);
1066 int64_t src2_val = src2.Int(vform, i);
1067 int64_t dst_val;
1068 if (max == true) {
1069 dst_val = (src1_val > src2_val) ? src1_val : src2_val;
1070 } else {
1071 dst_val = (src1_val < src2_val) ? src1_val : src2_val;
1072 }
1073 dst.SetInt(vform, i, dst_val);
1074 }
1075 return dst;
1076 }
1077
1078
smax(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1079 LogicVRegister Simulator::smax(VectorFormat vform,
1080 LogicVRegister dst,
1081 const LogicVRegister& src1,
1082 const LogicVRegister& src2) {
1083 return sminmax(vform, dst, src1, src2, true);
1084 }
1085
1086
smin(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1087 LogicVRegister Simulator::smin(VectorFormat vform,
1088 LogicVRegister dst,
1089 const LogicVRegister& src1,
1090 const LogicVRegister& src2) {
1091 return sminmax(vform, dst, src1, src2, false);
1092 }
1093
1094
sminmaxp(VectorFormat vform,LogicVRegister dst,int dst_index,const LogicVRegister & src,bool max)1095 LogicVRegister Simulator::sminmaxp(VectorFormat vform,
1096 LogicVRegister dst,
1097 int dst_index,
1098 const LogicVRegister& src,
1099 bool max) {
1100 for (int i = 0; i < LaneCountFromFormat(vform); i += 2) {
1101 int64_t src1_val = src.Int(vform, i);
1102 int64_t src2_val = src.Int(vform, i + 1);
1103 int64_t dst_val;
1104 if (max == true) {
1105 dst_val = (src1_val > src2_val) ? src1_val : src2_val;
1106 } else {
1107 dst_val = (src1_val < src2_val) ? src1_val : src2_val;
1108 }
1109 dst.SetInt(vform, dst_index + (i >> 1), dst_val);
1110 }
1111 return dst;
1112 }
1113
1114
smaxp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1115 LogicVRegister Simulator::smaxp(VectorFormat vform,
1116 LogicVRegister dst,
1117 const LogicVRegister& src1,
1118 const LogicVRegister& src2) {
1119 dst.ClearForWrite(vform);
1120 sminmaxp(vform, dst, 0, src1, true);
1121 sminmaxp(vform, dst, LaneCountFromFormat(vform) >> 1, src2, true);
1122 return dst;
1123 }
1124
1125
sminp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1126 LogicVRegister Simulator::sminp(VectorFormat vform,
1127 LogicVRegister dst,
1128 const LogicVRegister& src1,
1129 const LogicVRegister& src2) {
1130 dst.ClearForWrite(vform);
1131 sminmaxp(vform, dst, 0, src1, false);
1132 sminmaxp(vform, dst, LaneCountFromFormat(vform) >> 1, src2, false);
1133 return dst;
1134 }
1135
1136
addp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1137 LogicVRegister Simulator::addp(VectorFormat vform,
1138 LogicVRegister dst,
1139 const LogicVRegister& src) {
1140 VIXL_ASSERT(vform == kFormatD);
1141
1142 int64_t dst_val = src.Int(kFormat2D, 0) + src.Int(kFormat2D, 1);
1143 dst.ClearForWrite(vform);
1144 dst.SetInt(vform, 0, dst_val);
1145 return dst;
1146 }
1147
1148
addv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1149 LogicVRegister Simulator::addv(VectorFormat vform,
1150 LogicVRegister dst,
1151 const LogicVRegister& src) {
1152 VectorFormat vform_dst
1153 = ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
1154
1155
1156 int64_t dst_val = 0;
1157 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1158 dst_val += src.Int(vform, i);
1159 }
1160
1161 dst.ClearForWrite(vform_dst);
1162 dst.SetInt(vform_dst, 0, dst_val);
1163 return dst;
1164 }
1165
1166
saddlv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1167 LogicVRegister Simulator::saddlv(VectorFormat vform,
1168 LogicVRegister dst,
1169 const LogicVRegister& src) {
1170 VectorFormat vform_dst
1171 = ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform) * 2);
1172
1173 int64_t dst_val = 0;
1174 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1175 dst_val += src.Int(vform, i);
1176 }
1177
1178 dst.ClearForWrite(vform_dst);
1179 dst.SetInt(vform_dst, 0, dst_val);
1180 return dst;
1181 }
1182
1183
uaddlv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1184 LogicVRegister Simulator::uaddlv(VectorFormat vform,
1185 LogicVRegister dst,
1186 const LogicVRegister& src) {
1187 VectorFormat vform_dst
1188 = ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform) * 2);
1189
1190 uint64_t dst_val = 0;
1191 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1192 dst_val += src.Uint(vform, i);
1193 }
1194
1195 dst.ClearForWrite(vform_dst);
1196 dst.SetUint(vform_dst, 0, dst_val);
1197 return dst;
1198 }
1199
1200
sminmaxv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,bool max)1201 LogicVRegister Simulator::sminmaxv(VectorFormat vform,
1202 LogicVRegister dst,
1203 const LogicVRegister& src,
1204 bool max) {
1205 dst.ClearForWrite(vform);
1206 int64_t dst_val = max ? INT64_MIN : INT64_MAX;
1207 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1208 int64_t src_val = src.Int(vform, i);
1209 if (max == true) {
1210 dst_val = (src_val > dst_val) ? src_val : dst_val;
1211 } else {
1212 dst_val = (src_val < dst_val) ? src_val : dst_val;
1213 }
1214 }
1215 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1216 dst.SetInt(vform, i, 0);
1217 }
1218 dst.SetInt(vform, 0, dst_val);
1219 return dst;
1220 }
1221
1222
smaxv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1223 LogicVRegister Simulator::smaxv(VectorFormat vform,
1224 LogicVRegister dst,
1225 const LogicVRegister& src) {
1226 sminmaxv(vform, dst, src, true);
1227 return dst;
1228 }
1229
1230
sminv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1231 LogicVRegister Simulator::sminv(VectorFormat vform,
1232 LogicVRegister dst,
1233 const LogicVRegister& src) {
1234 sminmaxv(vform, dst, src, false);
1235 return dst;
1236 }
1237
1238
uminmax(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,bool max)1239 LogicVRegister Simulator::uminmax(VectorFormat vform,
1240 LogicVRegister dst,
1241 const LogicVRegister& src1,
1242 const LogicVRegister& src2,
1243 bool max) {
1244 dst.ClearForWrite(vform);
1245 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1246 uint64_t src1_val = src1.Uint(vform, i);
1247 uint64_t src2_val = src2.Uint(vform, i);
1248 uint64_t dst_val;
1249 if (max == true) {
1250 dst_val = (src1_val > src2_val) ? src1_val : src2_val;
1251 } else {
1252 dst_val = (src1_val < src2_val) ? src1_val : src2_val;
1253 }
1254 dst.SetUint(vform, i, dst_val);
1255 }
1256 return dst;
1257 }
1258
1259
umax(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1260 LogicVRegister Simulator::umax(VectorFormat vform,
1261 LogicVRegister dst,
1262 const LogicVRegister& src1,
1263 const LogicVRegister& src2) {
1264 return uminmax(vform, dst, src1, src2, true);
1265 }
1266
1267
umin(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1268 LogicVRegister Simulator::umin(VectorFormat vform,
1269 LogicVRegister dst,
1270 const LogicVRegister& src1,
1271 const LogicVRegister& src2) {
1272 return uminmax(vform, dst, src1, src2, false);
1273 }
1274
1275
uminmaxp(VectorFormat vform,LogicVRegister dst,int dst_index,const LogicVRegister & src,bool max)1276 LogicVRegister Simulator::uminmaxp(VectorFormat vform,
1277 LogicVRegister dst,
1278 int dst_index,
1279 const LogicVRegister& src,
1280 bool max) {
1281 for (int i = 0; i < LaneCountFromFormat(vform); i += 2) {
1282 uint64_t src1_val = src.Uint(vform, i);
1283 uint64_t src2_val = src.Uint(vform, i + 1);
1284 uint64_t dst_val;
1285 if (max == true) {
1286 dst_val = (src1_val > src2_val) ? src1_val : src2_val;
1287 } else {
1288 dst_val = (src1_val < src2_val) ? src1_val : src2_val;
1289 }
1290 dst.SetUint(vform, dst_index + (i >> 1), dst_val);
1291 }
1292 return dst;
1293 }
1294
1295
umaxp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1296 LogicVRegister Simulator::umaxp(VectorFormat vform,
1297 LogicVRegister dst,
1298 const LogicVRegister& src1,
1299 const LogicVRegister& src2) {
1300 dst.ClearForWrite(vform);
1301 uminmaxp(vform, dst, 0, src1, true);
1302 uminmaxp(vform, dst, LaneCountFromFormat(vform) >> 1, src2, true);
1303 return dst;
1304 }
1305
1306
uminp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1307 LogicVRegister Simulator::uminp(VectorFormat vform,
1308 LogicVRegister dst,
1309 const LogicVRegister& src1,
1310 const LogicVRegister& src2) {
1311 dst.ClearForWrite(vform);
1312 uminmaxp(vform, dst, 0, src1, false);
1313 uminmaxp(vform, dst, LaneCountFromFormat(vform) >> 1, src2, false);
1314 return dst;
1315 }
1316
1317
uminmaxv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,bool max)1318 LogicVRegister Simulator::uminmaxv(VectorFormat vform,
1319 LogicVRegister dst,
1320 const LogicVRegister& src,
1321 bool max) {
1322 dst.ClearForWrite(vform);
1323 uint64_t dst_val = max ? 0 : UINT64_MAX;
1324 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1325 uint64_t src_val = src.Uint(vform, i);
1326 if (max == true) {
1327 dst_val = (src_val > dst_val) ? src_val : dst_val;
1328 } else {
1329 dst_val = (src_val < dst_val) ? src_val : dst_val;
1330 }
1331 }
1332 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1333 dst.SetUint(vform, i, 0);
1334 }
1335 dst.SetUint(vform, 0, dst_val);
1336 return dst;
1337 }
1338
1339
umaxv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1340 LogicVRegister Simulator::umaxv(VectorFormat vform,
1341 LogicVRegister dst,
1342 const LogicVRegister& src) {
1343 uminmaxv(vform, dst, src, true);
1344 return dst;
1345 }
1346
1347
uminv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1348 LogicVRegister Simulator::uminv(VectorFormat vform,
1349 LogicVRegister dst,
1350 const LogicVRegister& src) {
1351 uminmaxv(vform, dst, src, false);
1352 return dst;
1353 }
1354
1355
shl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1356 LogicVRegister Simulator::shl(VectorFormat vform,
1357 LogicVRegister dst,
1358 const LogicVRegister& src,
1359 int shift) {
1360 VIXL_ASSERT(shift >= 0);
1361 SimVRegister temp;
1362 LogicVRegister shiftreg = dup_immediate(vform, temp, shift);
1363 return ushl(vform, dst, src, shiftreg);
1364 }
1365
1366
sshll(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1367 LogicVRegister Simulator::sshll(VectorFormat vform,
1368 LogicVRegister dst,
1369 const LogicVRegister& src,
1370 int shift) {
1371 VIXL_ASSERT(shift >= 0);
1372 SimVRegister temp1, temp2;
1373 LogicVRegister shiftreg = dup_immediate(vform, temp1, shift);
1374 LogicVRegister extendedreg = sxtl(vform, temp2, src);
1375 return sshl(vform, dst, extendedreg, shiftreg);
1376 }
1377
1378
sshll2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1379 LogicVRegister Simulator::sshll2(VectorFormat vform,
1380 LogicVRegister dst,
1381 const LogicVRegister& src,
1382 int shift) {
1383 VIXL_ASSERT(shift >= 0);
1384 SimVRegister temp1, temp2;
1385 LogicVRegister shiftreg = dup_immediate(vform, temp1, shift);
1386 LogicVRegister extendedreg = sxtl2(vform, temp2, src);
1387 return sshl(vform, dst, extendedreg, shiftreg);
1388 }
1389
1390
shll(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1391 LogicVRegister Simulator::shll(VectorFormat vform,
1392 LogicVRegister dst,
1393 const LogicVRegister& src) {
1394 int shift = LaneSizeInBitsFromFormat(vform) / 2;
1395 return sshll(vform, dst, src, shift);
1396 }
1397
1398
shll2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1399 LogicVRegister Simulator::shll2(VectorFormat vform,
1400 LogicVRegister dst,
1401 const LogicVRegister& src) {
1402 int shift = LaneSizeInBitsFromFormat(vform) / 2;
1403 return sshll2(vform, dst, src, shift);
1404 }
1405
1406
ushll(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1407 LogicVRegister Simulator::ushll(VectorFormat vform,
1408 LogicVRegister dst,
1409 const LogicVRegister& src,
1410 int shift) {
1411 VIXL_ASSERT(shift >= 0);
1412 SimVRegister temp1, temp2;
1413 LogicVRegister shiftreg = dup_immediate(vform, temp1, shift);
1414 LogicVRegister extendedreg = uxtl(vform, temp2, src);
1415 return ushl(vform, dst, extendedreg, shiftreg);
1416 }
1417
1418
ushll2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1419 LogicVRegister Simulator::ushll2(VectorFormat vform,
1420 LogicVRegister dst,
1421 const LogicVRegister& src,
1422 int shift) {
1423 VIXL_ASSERT(shift >= 0);
1424 SimVRegister temp1, temp2;
1425 LogicVRegister shiftreg = dup_immediate(vform, temp1, shift);
1426 LogicVRegister extendedreg = uxtl2(vform, temp2, src);
1427 return ushl(vform, dst, extendedreg, shiftreg);
1428 }
1429
1430
sli(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1431 LogicVRegister Simulator::sli(VectorFormat vform,
1432 LogicVRegister dst,
1433 const LogicVRegister& src,
1434 int shift) {
1435 dst.ClearForWrite(vform);
1436 int laneCount = LaneCountFromFormat(vform);
1437 for (int i = 0; i < laneCount; i++) {
1438 uint64_t src_lane = src.Uint(vform, i);
1439 uint64_t dst_lane = dst.Uint(vform, i);
1440 uint64_t shifted = src_lane << shift;
1441 uint64_t mask = MaxUintFromFormat(vform) << shift;
1442 dst.SetUint(vform, i, (dst_lane & ~mask) | shifted);
1443 }
1444 return dst;
1445 }
1446
1447
sqshl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1448 LogicVRegister Simulator::sqshl(VectorFormat vform,
1449 LogicVRegister dst,
1450 const LogicVRegister& src,
1451 int shift) {
1452 VIXL_ASSERT(shift >= 0);
1453 SimVRegister temp;
1454 LogicVRegister shiftreg = dup_immediate(vform, temp, shift);
1455 return sshl(vform, dst, src, shiftreg).SignedSaturate(vform);
1456 }
1457
1458
uqshl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1459 LogicVRegister Simulator::uqshl(VectorFormat vform,
1460 LogicVRegister dst,
1461 const LogicVRegister& src,
1462 int shift) {
1463 VIXL_ASSERT(shift >= 0);
1464 SimVRegister temp;
1465 LogicVRegister shiftreg = dup_immediate(vform, temp, shift);
1466 return ushl(vform, dst, src, shiftreg).UnsignedSaturate(vform);
1467 }
1468
1469
sqshlu(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1470 LogicVRegister Simulator::sqshlu(VectorFormat vform,
1471 LogicVRegister dst,
1472 const LogicVRegister& src,
1473 int shift) {
1474 VIXL_ASSERT(shift >= 0);
1475 SimVRegister temp;
1476 LogicVRegister shiftreg = dup_immediate(vform, temp, shift);
1477 return sshl(vform, dst, src, shiftreg).UnsignedSaturate(vform);
1478 }
1479
1480
sri(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1481 LogicVRegister Simulator::sri(VectorFormat vform,
1482 LogicVRegister dst,
1483 const LogicVRegister& src,
1484 int shift) {
1485 dst.ClearForWrite(vform);
1486 int laneCount = LaneCountFromFormat(vform);
1487 VIXL_ASSERT((shift > 0) &&
1488 (shift <= static_cast<int>(LaneSizeInBitsFromFormat(vform))));
1489 for (int i = 0; i < laneCount; i++) {
1490 uint64_t src_lane = src.Uint(vform, i);
1491 uint64_t dst_lane = dst.Uint(vform, i);
1492 uint64_t shifted;
1493 uint64_t mask;
1494 if (shift == 64) {
1495 shifted = 0;
1496 mask = 0;
1497 } else {
1498 shifted = src_lane >> shift;
1499 mask = MaxUintFromFormat(vform) >> shift;
1500 }
1501 dst.SetUint(vform, i, (dst_lane & ~mask) | shifted);
1502 }
1503 return dst;
1504 }
1505
1506
ushr(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1507 LogicVRegister Simulator::ushr(VectorFormat vform,
1508 LogicVRegister dst,
1509 const LogicVRegister& src,
1510 int shift) {
1511 VIXL_ASSERT(shift >= 0);
1512 SimVRegister temp;
1513 LogicVRegister shiftreg = dup_immediate(vform, temp, -shift);
1514 return ushl(vform, dst, src, shiftreg);
1515 }
1516
1517
sshr(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1518 LogicVRegister Simulator::sshr(VectorFormat vform,
1519 LogicVRegister dst,
1520 const LogicVRegister& src,
1521 int shift) {
1522 VIXL_ASSERT(shift >= 0);
1523 SimVRegister temp;
1524 LogicVRegister shiftreg = dup_immediate(vform, temp, -shift);
1525 return sshl(vform, dst, src, shiftreg);
1526 }
1527
1528
ssra(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1529 LogicVRegister Simulator::ssra(VectorFormat vform,
1530 LogicVRegister dst,
1531 const LogicVRegister& src,
1532 int shift) {
1533 SimVRegister temp;
1534 LogicVRegister shifted_reg = sshr(vform, temp, src, shift);
1535 return add(vform, dst, dst, shifted_reg);
1536 }
1537
1538
usra(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1539 LogicVRegister Simulator::usra(VectorFormat vform,
1540 LogicVRegister dst,
1541 const LogicVRegister& src,
1542 int shift) {
1543 SimVRegister temp;
1544 LogicVRegister shifted_reg = ushr(vform, temp, src, shift);
1545 return add(vform, dst, dst, shifted_reg);
1546 }
1547
1548
srsra(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1549 LogicVRegister Simulator::srsra(VectorFormat vform,
1550 LogicVRegister dst,
1551 const LogicVRegister& src,
1552 int shift) {
1553 SimVRegister temp;
1554 LogicVRegister shifted_reg = sshr(vform, temp, src, shift).Round(vform);
1555 return add(vform, dst, dst, shifted_reg);
1556 }
1557
1558
ursra(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)1559 LogicVRegister Simulator::ursra(VectorFormat vform,
1560 LogicVRegister dst,
1561 const LogicVRegister& src,
1562 int shift) {
1563 SimVRegister temp;
1564 LogicVRegister shifted_reg = ushr(vform, temp, src, shift).Round(vform);
1565 return add(vform, dst, dst, shifted_reg);
1566 }
1567
1568
cls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1569 LogicVRegister Simulator::cls(VectorFormat vform,
1570 LogicVRegister dst,
1571 const LogicVRegister& src) {
1572 uint64_t result[16];
1573 int laneSizeInBits = LaneSizeInBitsFromFormat(vform);
1574 int laneCount = LaneCountFromFormat(vform);
1575 for (int i = 0; i < laneCount; i++) {
1576 result[i] = CountLeadingSignBits(src.Int(vform, i), laneSizeInBits);
1577 }
1578
1579 dst.ClearForWrite(vform);
1580 for (int i = 0; i < laneCount; ++i) {
1581 dst.SetUint(vform, i, result[i]);
1582 }
1583 return dst;
1584 }
1585
1586
clz(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1587 LogicVRegister Simulator::clz(VectorFormat vform,
1588 LogicVRegister dst,
1589 const LogicVRegister& src) {
1590 uint64_t result[16];
1591 int laneSizeInBits = LaneSizeInBitsFromFormat(vform);
1592 int laneCount = LaneCountFromFormat(vform);
1593 for (int i = 0; i < laneCount; i++) {
1594 result[i] = CountLeadingZeros(src.Uint(vform, i), laneSizeInBits);
1595 }
1596
1597 dst.ClearForWrite(vform);
1598 for (int i = 0; i < laneCount; ++i) {
1599 dst.SetUint(vform, i, result[i]);
1600 }
1601 return dst;
1602 }
1603
1604
cnt(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1605 LogicVRegister Simulator::cnt(VectorFormat vform,
1606 LogicVRegister dst,
1607 const LogicVRegister& src) {
1608 uint64_t result[16];
1609 int laneSizeInBits = LaneSizeInBitsFromFormat(vform);
1610 int laneCount = LaneCountFromFormat(vform);
1611 for (int i = 0; i < laneCount; i++) {
1612 uint64_t value = src.Uint(vform, i);
1613 result[i] = 0;
1614 for (int j = 0; j < laneSizeInBits; j++) {
1615 result[i] += (value & 1);
1616 value >>= 1;
1617 }
1618 }
1619
1620 dst.ClearForWrite(vform);
1621 for (int i = 0; i < laneCount; ++i) {
1622 dst.SetUint(vform, i, result[i]);
1623 }
1624 return dst;
1625 }
1626
1627
sshl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1628 LogicVRegister Simulator::sshl(VectorFormat vform,
1629 LogicVRegister dst,
1630 const LogicVRegister& src1,
1631 const LogicVRegister& src2) {
1632 dst.ClearForWrite(vform);
1633 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1634 int8_t shift_val = src2.Int(vform, i);
1635 int64_t lj_src_val = src1.IntLeftJustified(vform, i);
1636
1637 // Set signed saturation state.
1638 if ((shift_val > CountLeadingSignBits(lj_src_val)) &&
1639 (lj_src_val != 0)) {
1640 dst.SetSignedSat(i, lj_src_val >= 0);
1641 }
1642
1643 // Set unsigned saturation state.
1644 if (lj_src_val < 0) {
1645 dst.SetUnsignedSat(i, false);
1646 } else if ((shift_val > CountLeadingZeros(lj_src_val)) &&
1647 (lj_src_val != 0)) {
1648 dst.SetUnsignedSat(i, true);
1649 }
1650
1651 int64_t src_val = src1.Int(vform, i);
1652 if (shift_val > 63) {
1653 dst.SetInt(vform, i, 0);
1654 } else if (shift_val < -63) {
1655 dst.SetRounding(i, src_val < 0);
1656 dst.SetInt(vform, i, (src_val < 0) ? -1 : 0);
1657 } else {
1658 if (shift_val < 0) {
1659 // Set rounding state. Rounding only needed on right shifts.
1660 if (((src_val >> (-shift_val - 1)) & 1) == 1) {
1661 dst.SetRounding(i, true);
1662 }
1663 src_val >>= -shift_val;
1664 } else {
1665 src_val <<= shift_val;
1666 }
1667 dst.SetInt(vform, i, src_val);
1668 }
1669 }
1670 return dst;
1671 }
1672
1673
ushl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1674 LogicVRegister Simulator::ushl(VectorFormat vform,
1675 LogicVRegister dst,
1676 const LogicVRegister& src1,
1677 const LogicVRegister& src2) {
1678 dst.ClearForWrite(vform);
1679 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1680 int8_t shift_val = src2.Int(vform, i);
1681 uint64_t lj_src_val = src1.UintLeftJustified(vform, i);
1682
1683 // Set saturation state.
1684 if ((shift_val > CountLeadingZeros(lj_src_val)) && (lj_src_val != 0)) {
1685 dst.SetUnsignedSat(i, true);
1686 }
1687
1688 uint64_t src_val = src1.Uint(vform, i);
1689 if ((shift_val > 63) || (shift_val < -64)) {
1690 dst.SetUint(vform, i, 0);
1691 } else {
1692 if (shift_val < 0) {
1693 // Set rounding state. Rounding only needed on right shifts.
1694 if (((src_val >> (-shift_val - 1)) & 1) == 1) {
1695 dst.SetRounding(i, true);
1696 }
1697
1698 if (shift_val == -64) {
1699 src_val = 0;
1700 } else {
1701 src_val >>= -shift_val;
1702 }
1703 } else {
1704 src_val <<= shift_val;
1705 }
1706 dst.SetUint(vform, i, src_val);
1707 }
1708 }
1709 return dst;
1710 }
1711
1712
neg(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1713 LogicVRegister Simulator::neg(VectorFormat vform,
1714 LogicVRegister dst,
1715 const LogicVRegister& src) {
1716 dst.ClearForWrite(vform);
1717 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1718 // Test for signed saturation.
1719 int64_t sa = src.Int(vform, i);
1720 if (sa == MinIntFromFormat(vform)) {
1721 dst.SetSignedSat(i, true);
1722 }
1723 dst.SetInt(vform, i, -sa);
1724 }
1725 return dst;
1726 }
1727
1728
suqadd(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1729 LogicVRegister Simulator::suqadd(VectorFormat vform,
1730 LogicVRegister dst,
1731 const LogicVRegister& src) {
1732 dst.ClearForWrite(vform);
1733 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1734 int64_t sa = dst.IntLeftJustified(vform, i);
1735 uint64_t ub = src.UintLeftJustified(vform, i);
1736 int64_t sr = sa + ub;
1737
1738 if (sr < sa) { // Test for signed positive saturation.
1739 dst.SetInt(vform, i, MaxIntFromFormat(vform));
1740 } else {
1741 dst.SetInt(vform, i, dst.Int(vform, i) + src.Int(vform, i));
1742 }
1743 }
1744 return dst;
1745 }
1746
1747
usqadd(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1748 LogicVRegister Simulator::usqadd(VectorFormat vform,
1749 LogicVRegister dst,
1750 const LogicVRegister& src) {
1751 dst.ClearForWrite(vform);
1752 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1753 uint64_t ua = dst.UintLeftJustified(vform, i);
1754 int64_t sb = src.IntLeftJustified(vform, i);
1755 uint64_t ur = ua + sb;
1756
1757 if ((sb > 0) && (ur <= ua)) {
1758 dst.SetUint(vform, i, MaxUintFromFormat(vform)); // Positive saturation.
1759 } else if ((sb < 0) && (ur >= ua)) {
1760 dst.SetUint(vform, i, 0); // Negative saturation.
1761 } else {
1762 dst.SetUint(vform, i, dst.Uint(vform, i) + src.Int(vform, i));
1763 }
1764 }
1765 return dst;
1766 }
1767
1768
abs(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1769 LogicVRegister Simulator::abs(VectorFormat vform,
1770 LogicVRegister dst,
1771 const LogicVRegister& src) {
1772 dst.ClearForWrite(vform);
1773 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1774 // Test for signed saturation.
1775 int64_t sa = src.Int(vform, i);
1776 if (sa == MinIntFromFormat(vform)) {
1777 dst.SetSignedSat(i, true);
1778 }
1779 if (sa < 0) {
1780 dst.SetInt(vform, i, -sa);
1781 } else {
1782 dst.SetInt(vform, i, sa);
1783 }
1784 }
1785 return dst;
1786 }
1787
1788
extractnarrow(VectorFormat dstform,LogicVRegister dst,bool dstIsSigned,const LogicVRegister & src,bool srcIsSigned)1789 LogicVRegister Simulator::extractnarrow(VectorFormat dstform,
1790 LogicVRegister dst,
1791 bool dstIsSigned,
1792 const LogicVRegister& src,
1793 bool srcIsSigned) {
1794 bool upperhalf = false;
1795 VectorFormat srcform = kFormatUndefined;
1796 int64_t ssrc[8];
1797 uint64_t usrc[8];
1798
1799 switch (dstform) {
1800 case kFormat8B : upperhalf = false; srcform = kFormat8H; break;
1801 case kFormat16B: upperhalf = true; srcform = kFormat8H; break;
1802 case kFormat4H : upperhalf = false; srcform = kFormat4S; break;
1803 case kFormat8H : upperhalf = true; srcform = kFormat4S; break;
1804 case kFormat2S : upperhalf = false; srcform = kFormat2D; break;
1805 case kFormat4S : upperhalf = true; srcform = kFormat2D; break;
1806 case kFormatB : upperhalf = false; srcform = kFormatH; break;
1807 case kFormatH : upperhalf = false; srcform = kFormatS; break;
1808 case kFormatS : upperhalf = false; srcform = kFormatD; break;
1809 default:VIXL_UNIMPLEMENTED();
1810 }
1811
1812 for (int i = 0; i < LaneCountFromFormat(srcform); i++) {
1813 ssrc[i] = src.Int(srcform, i);
1814 usrc[i] = src.Uint(srcform, i);
1815 }
1816
1817 int offset;
1818 if (upperhalf) {
1819 offset = LaneCountFromFormat(dstform) / 2;
1820 } else {
1821 offset = 0;
1822 dst.ClearForWrite(dstform);
1823 }
1824
1825 for (int i = 0; i < LaneCountFromFormat(srcform); i++) {
1826 // Test for signed saturation
1827 if (ssrc[i] > MaxIntFromFormat(dstform)) {
1828 dst.SetSignedSat(offset + i, true);
1829 } else if (ssrc[i] < MinIntFromFormat(dstform)) {
1830 dst.SetSignedSat(offset + i, false);
1831 }
1832
1833 // Test for unsigned saturation
1834 if (srcIsSigned) {
1835 if (ssrc[i] > static_cast<int64_t>(MaxUintFromFormat(dstform))) {
1836 dst.SetUnsignedSat(offset + i, true);
1837 } else if (ssrc[i] < 0) {
1838 dst.SetUnsignedSat(offset + i, false);
1839 }
1840 } else {
1841 if (usrc[i] > MaxUintFromFormat(dstform)) {
1842 dst.SetUnsignedSat(offset + i, true);
1843 }
1844 }
1845
1846 int64_t result;
1847 if (srcIsSigned) {
1848 result = ssrc[i] & MaxUintFromFormat(dstform);
1849 } else {
1850 result = usrc[i] & MaxUintFromFormat(dstform);
1851 }
1852
1853 if (dstIsSigned) {
1854 dst.SetInt(dstform, offset + i, result);
1855 } else {
1856 dst.SetUint(dstform, offset + i, result);
1857 }
1858 }
1859 return dst;
1860 }
1861
1862
xtn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1863 LogicVRegister Simulator::xtn(VectorFormat vform,
1864 LogicVRegister dst,
1865 const LogicVRegister& src) {
1866 return extractnarrow(vform, dst, true, src, true);
1867 }
1868
1869
sqxtn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1870 LogicVRegister Simulator::sqxtn(VectorFormat vform,
1871 LogicVRegister dst,
1872 const LogicVRegister& src) {
1873 return extractnarrow(vform, dst, true, src, true).SignedSaturate(vform);
1874 }
1875
1876
sqxtun(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1877 LogicVRegister Simulator::sqxtun(VectorFormat vform,
1878 LogicVRegister dst,
1879 const LogicVRegister& src) {
1880 return extractnarrow(vform, dst, false, src, true).UnsignedSaturate(vform);
1881 }
1882
1883
uqxtn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1884 LogicVRegister Simulator::uqxtn(VectorFormat vform,
1885 LogicVRegister dst,
1886 const LogicVRegister& src) {
1887 return extractnarrow(vform, dst, false, src, false).UnsignedSaturate(vform);
1888 }
1889
1890
absdiff(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,bool issigned)1891 LogicVRegister Simulator::absdiff(VectorFormat vform,
1892 LogicVRegister dst,
1893 const LogicVRegister& src1,
1894 const LogicVRegister& src2,
1895 bool issigned) {
1896 dst.ClearForWrite(vform);
1897 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1898 if (issigned) {
1899 int64_t sr = src1.Int(vform, i) - src2.Int(vform, i);
1900 sr = sr > 0 ? sr : -sr;
1901 dst.SetInt(vform, i, sr);
1902 } else {
1903 int64_t sr = src1.Uint(vform, i) - src2.Uint(vform, i);
1904 sr = sr > 0 ? sr : -sr;
1905 dst.SetUint(vform, i, sr);
1906 }
1907 }
1908 return dst;
1909 }
1910
1911
saba(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1912 LogicVRegister Simulator::saba(VectorFormat vform,
1913 LogicVRegister dst,
1914 const LogicVRegister& src1,
1915 const LogicVRegister& src2) {
1916 SimVRegister temp;
1917 dst.ClearForWrite(vform);
1918 absdiff(vform, temp, src1, src2, true);
1919 add(vform, dst, dst, temp);
1920 return dst;
1921 }
1922
1923
uaba(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)1924 LogicVRegister Simulator::uaba(VectorFormat vform,
1925 LogicVRegister dst,
1926 const LogicVRegister& src1,
1927 const LogicVRegister& src2) {
1928 SimVRegister temp;
1929 dst.ClearForWrite(vform);
1930 absdiff(vform, temp, src1, src2, false);
1931 add(vform, dst, dst, temp);
1932 return dst;
1933 }
1934
1935
not_(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1936 LogicVRegister Simulator::not_(VectorFormat vform,
1937 LogicVRegister dst,
1938 const LogicVRegister& src) {
1939 dst.ClearForWrite(vform);
1940 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
1941 dst.SetUint(vform, i, ~src.Uint(vform, i));
1942 }
1943 return dst;
1944 }
1945
1946
rbit(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1947 LogicVRegister Simulator::rbit(VectorFormat vform,
1948 LogicVRegister dst,
1949 const LogicVRegister& src) {
1950 uint64_t result[16];
1951 int laneCount = LaneCountFromFormat(vform);
1952 int laneSizeInBits = LaneSizeInBitsFromFormat(vform);
1953 uint64_t reversed_value;
1954 uint64_t value;
1955 for (int i = 0; i < laneCount; i++) {
1956 value = src.Uint(vform, i);
1957 reversed_value = 0;
1958 for (int j = 0; j < laneSizeInBits; j++) {
1959 reversed_value = (reversed_value << 1) | (value & 1);
1960 value >>= 1;
1961 }
1962 result[i] = reversed_value;
1963 }
1964
1965 dst.ClearForWrite(vform);
1966 for (int i = 0; i < laneCount; ++i) {
1967 dst.SetUint(vform, i, result[i]);
1968 }
1969 return dst;
1970 }
1971
1972
rev(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int revSize)1973 LogicVRegister Simulator::rev(VectorFormat vform,
1974 LogicVRegister dst,
1975 const LogicVRegister& src,
1976 int revSize) {
1977 uint64_t result[16];
1978 int laneCount = LaneCountFromFormat(vform);
1979 int laneSize = LaneSizeInBytesFromFormat(vform);
1980 int lanesPerLoop = revSize / laneSize;
1981 for (int i = 0; i < laneCount; i += lanesPerLoop) {
1982 for (int j = 0; j < lanesPerLoop; j++) {
1983 result[i + lanesPerLoop - 1 - j] = src.Uint(vform, i + j);
1984 }
1985 }
1986 dst.ClearForWrite(vform);
1987 for (int i = 0; i < laneCount; ++i) {
1988 dst.SetUint(vform, i, result[i]);
1989 }
1990 return dst;
1991 }
1992
1993
rev16(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)1994 LogicVRegister Simulator::rev16(VectorFormat vform,
1995 LogicVRegister dst,
1996 const LogicVRegister& src) {
1997 return rev(vform, dst, src, 2);
1998 }
1999
2000
rev32(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2001 LogicVRegister Simulator::rev32(VectorFormat vform,
2002 LogicVRegister dst,
2003 const LogicVRegister& src) {
2004 return rev(vform, dst, src, 4);
2005 }
2006
2007
rev64(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2008 LogicVRegister Simulator::rev64(VectorFormat vform,
2009 LogicVRegister dst,
2010 const LogicVRegister& src) {
2011 return rev(vform, dst, src, 8);
2012 }
2013
2014
addlp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,bool is_signed,bool do_accumulate)2015 LogicVRegister Simulator::addlp(VectorFormat vform,
2016 LogicVRegister dst,
2017 const LogicVRegister& src,
2018 bool is_signed,
2019 bool do_accumulate) {
2020 VectorFormat vformsrc = VectorFormatHalfWidthDoubleLanes(vform);
2021
2022 int64_t sr[16];
2023 uint64_t ur[16];
2024
2025 int laneCount = LaneCountFromFormat(vform);
2026 for (int i = 0; i < laneCount; ++i) {
2027 if (is_signed) {
2028 sr[i] = src.Int(vformsrc, 2 * i) + src.Int(vformsrc, 2 * i + 1);
2029 } else {
2030 ur[i] = src.Uint(vformsrc, 2 * i) + src.Uint(vformsrc, 2 * i + 1);
2031 }
2032 }
2033
2034 dst.ClearForWrite(vform);
2035 for (int i = 0; i < laneCount; ++i) {
2036 if (do_accumulate) {
2037 if (is_signed) {
2038 dst.SetInt(vform, i, dst.Int(vform, i) + sr[i]);
2039 } else {
2040 dst.SetUint(vform, i, dst.Uint(vform, i) + ur[i]);
2041 }
2042 } else {
2043 if (is_signed) {
2044 dst.SetInt(vform, i, sr[i]);
2045 } else {
2046 dst.SetUint(vform, i, ur[i]);
2047 }
2048 }
2049 }
2050
2051 return dst;
2052 }
2053
2054
saddlp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2055 LogicVRegister Simulator::saddlp(VectorFormat vform,
2056 LogicVRegister dst,
2057 const LogicVRegister& src) {
2058 return addlp(vform, dst, src, true, false);
2059 }
2060
2061
uaddlp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2062 LogicVRegister Simulator::uaddlp(VectorFormat vform,
2063 LogicVRegister dst,
2064 const LogicVRegister& src) {
2065 return addlp(vform, dst, src, false, false);
2066 }
2067
2068
sadalp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2069 LogicVRegister Simulator::sadalp(VectorFormat vform,
2070 LogicVRegister dst,
2071 const LogicVRegister& src) {
2072 return addlp(vform, dst, src, true, true);
2073 }
2074
2075
uadalp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2076 LogicVRegister Simulator::uadalp(VectorFormat vform,
2077 LogicVRegister dst,
2078 const LogicVRegister& src) {
2079 return addlp(vform, dst, src, false, true);
2080 }
2081
2082
ext(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)2083 LogicVRegister Simulator::ext(VectorFormat vform,
2084 LogicVRegister dst,
2085 const LogicVRegister& src1,
2086 const LogicVRegister& src2,
2087 int index) {
2088 uint8_t result[16];
2089 int laneCount = LaneCountFromFormat(vform);
2090 for (int i = 0; i < laneCount - index; ++i) {
2091 result[i] = src1.Uint(vform, i + index);
2092 }
2093 for (int i = 0; i < index; ++i) {
2094 result[laneCount - index + i] = src2.Uint(vform, i);
2095 }
2096 dst.ClearForWrite(vform);
2097 for (int i = 0; i < laneCount; ++i) {
2098 dst.SetUint(vform, i, result[i]);
2099 }
2100 return dst;
2101 }
2102
2103
dup_element(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int src_index)2104 LogicVRegister Simulator::dup_element(VectorFormat vform,
2105 LogicVRegister dst,
2106 const LogicVRegister& src,
2107 int src_index) {
2108 int laneCount = LaneCountFromFormat(vform);
2109 uint64_t value = src.Uint(vform, src_index);
2110 dst.ClearForWrite(vform);
2111 for (int i = 0; i < laneCount; ++i) {
2112 dst.SetUint(vform, i, value);
2113 }
2114 return dst;
2115 }
2116
2117
dup_immediate(VectorFormat vform,LogicVRegister dst,uint64_t imm)2118 LogicVRegister Simulator::dup_immediate(VectorFormat vform,
2119 LogicVRegister dst,
2120 uint64_t imm) {
2121 int laneCount = LaneCountFromFormat(vform);
2122 uint64_t value = imm & MaxUintFromFormat(vform);
2123 dst.ClearForWrite(vform);
2124 for (int i = 0; i < laneCount; ++i) {
2125 dst.SetUint(vform, i, value);
2126 }
2127 return dst;
2128 }
2129
2130
ins_element(VectorFormat vform,LogicVRegister dst,int dst_index,const LogicVRegister & src,int src_index)2131 LogicVRegister Simulator::ins_element(VectorFormat vform,
2132 LogicVRegister dst,
2133 int dst_index,
2134 const LogicVRegister& src,
2135 int src_index) {
2136 dst.SetUint(vform, dst_index, src.Uint(vform, src_index));
2137 return dst;
2138 }
2139
2140
ins_immediate(VectorFormat vform,LogicVRegister dst,int dst_index,uint64_t imm)2141 LogicVRegister Simulator::ins_immediate(VectorFormat vform,
2142 LogicVRegister dst,
2143 int dst_index,
2144 uint64_t imm) {
2145 uint64_t value = imm & MaxUintFromFormat(vform);
2146 dst.SetUint(vform, dst_index, value);
2147 return dst;
2148 }
2149
2150
mov(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2151 LogicVRegister Simulator::mov(VectorFormat vform,
2152 LogicVRegister dst,
2153 const LogicVRegister& src) {
2154 dst.ClearForWrite(vform);
2155 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
2156 dst.SetUint(vform, lane, src.Uint(vform, lane));
2157 }
2158 return dst;
2159 }
2160
2161
movi(VectorFormat vform,LogicVRegister dst,uint64_t imm)2162 LogicVRegister Simulator::movi(VectorFormat vform,
2163 LogicVRegister dst,
2164 uint64_t imm) {
2165 int laneCount = LaneCountFromFormat(vform);
2166 dst.ClearForWrite(vform);
2167 for (int i = 0; i < laneCount; ++i) {
2168 dst.SetUint(vform, i, imm);
2169 }
2170 return dst;
2171 }
2172
2173
mvni(VectorFormat vform,LogicVRegister dst,uint64_t imm)2174 LogicVRegister Simulator::mvni(VectorFormat vform,
2175 LogicVRegister dst,
2176 uint64_t imm) {
2177 int laneCount = LaneCountFromFormat(vform);
2178 dst.ClearForWrite(vform);
2179 for (int i = 0; i < laneCount; ++i) {
2180 dst.SetUint(vform, i, ~imm);
2181 }
2182 return dst;
2183 }
2184
2185
orr(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,uint64_t imm)2186 LogicVRegister Simulator::orr(VectorFormat vform,
2187 LogicVRegister dst,
2188 const LogicVRegister& src,
2189 uint64_t imm) {
2190 uint64_t result[16];
2191 int laneCount = LaneCountFromFormat(vform);
2192 for (int i = 0; i < laneCount; ++i) {
2193 result[i] = src.Uint(vform, i) | imm;
2194 }
2195 dst.ClearForWrite(vform);
2196 for (int i = 0; i < laneCount; ++i) {
2197 dst.SetUint(vform, i, result[i]);
2198 }
2199 return dst;
2200 }
2201
2202
uxtl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2203 LogicVRegister Simulator::uxtl(VectorFormat vform,
2204 LogicVRegister dst,
2205 const LogicVRegister& src) {
2206 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2207
2208 dst.ClearForWrite(vform);
2209 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2210 dst.SetUint(vform, i, src.Uint(vform_half, i));
2211 }
2212 return dst;
2213 }
2214
2215
sxtl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2216 LogicVRegister Simulator::sxtl(VectorFormat vform,
2217 LogicVRegister dst,
2218 const LogicVRegister& src) {
2219 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2220
2221 dst.ClearForWrite(vform);
2222 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2223 dst.SetInt(vform, i, src.Int(vform_half, i));
2224 }
2225 return dst;
2226 }
2227
2228
uxtl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2229 LogicVRegister Simulator::uxtl2(VectorFormat vform,
2230 LogicVRegister dst,
2231 const LogicVRegister& src) {
2232 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2233 int lane_count = LaneCountFromFormat(vform);
2234
2235 dst.ClearForWrite(vform);
2236 for (int i = 0; i < lane_count; i++) {
2237 dst.SetUint(vform, i, src.Uint(vform_half, lane_count + i));
2238 }
2239 return dst;
2240 }
2241
2242
sxtl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)2243 LogicVRegister Simulator::sxtl2(VectorFormat vform,
2244 LogicVRegister dst,
2245 const LogicVRegister& src) {
2246 VectorFormat vform_half = VectorFormatHalfWidth(vform);
2247 int lane_count = LaneCountFromFormat(vform);
2248
2249 dst.ClearForWrite(vform);
2250 for (int i = 0; i < lane_count; i++) {
2251 dst.SetInt(vform, i, src.Int(vform_half, lane_count + i));
2252 }
2253 return dst;
2254 }
2255
2256
shrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2257 LogicVRegister Simulator::shrn(VectorFormat vform,
2258 LogicVRegister dst,
2259 const LogicVRegister& src,
2260 int shift) {
2261 SimVRegister temp;
2262 VectorFormat vform_src = VectorFormatDoubleWidth(vform);
2263 VectorFormat vform_dst = vform;
2264 LogicVRegister shifted_src = ushr(vform_src, temp, src, shift);
2265 return extractnarrow(vform_dst, dst, false, shifted_src, false);
2266 }
2267
2268
shrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2269 LogicVRegister Simulator::shrn2(VectorFormat vform,
2270 LogicVRegister dst,
2271 const LogicVRegister& src,
2272 int shift) {
2273 SimVRegister temp;
2274 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2275 VectorFormat vformdst = vform;
2276 LogicVRegister shifted_src = ushr(vformsrc, temp, src, shift);
2277 return extractnarrow(vformdst, dst, false, shifted_src, false);
2278 }
2279
2280
rshrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2281 LogicVRegister Simulator::rshrn(VectorFormat vform,
2282 LogicVRegister dst,
2283 const LogicVRegister& src,
2284 int shift) {
2285 SimVRegister temp;
2286 VectorFormat vformsrc = VectorFormatDoubleWidth(vform);
2287 VectorFormat vformdst = vform;
2288 LogicVRegister shifted_src = ushr(vformsrc, temp, src, shift).Round(vformsrc);
2289 return extractnarrow(vformdst, dst, false, shifted_src, false);
2290 }
2291
2292
rshrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2293 LogicVRegister Simulator::rshrn2(VectorFormat vform,
2294 LogicVRegister dst,
2295 const LogicVRegister& src,
2296 int shift) {
2297 SimVRegister temp;
2298 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2299 VectorFormat vformdst = vform;
2300 LogicVRegister shifted_src = ushr(vformsrc, temp, src, shift).Round(vformsrc);
2301 return extractnarrow(vformdst, dst, false, shifted_src, false);
2302 }
2303
2304
tbl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & ind)2305 LogicVRegister Simulator::tbl(VectorFormat vform,
2306 LogicVRegister dst,
2307 const LogicVRegister& tab,
2308 const LogicVRegister& ind) {
2309 SimVRegister result;
2310 movi(vform, result, 0);
2311 tbx(vform, result, tab, ind);
2312 return orr(vform, dst, result, result);
2313 }
2314
2315
tbl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & ind)2316 LogicVRegister Simulator::tbl(VectorFormat vform,
2317 LogicVRegister dst,
2318 const LogicVRegister& tab,
2319 const LogicVRegister& tab2,
2320 const LogicVRegister& ind) {
2321 SimVRegister result;
2322 movi(vform, result, 0);
2323 tbx(vform, result, tab, tab2, ind);
2324 return orr(vform, dst, result, result);
2325 }
2326
2327
tbl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & tab3,const LogicVRegister & ind)2328 LogicVRegister Simulator::tbl(VectorFormat vform,
2329 LogicVRegister dst,
2330 const LogicVRegister& tab,
2331 const LogicVRegister& tab2,
2332 const LogicVRegister& tab3,
2333 const LogicVRegister& ind) {
2334 SimVRegister result;
2335 movi(vform, result, 0);
2336 tbx(vform, result, tab, tab2, tab3, ind);
2337 return orr(vform, dst, result, result);
2338 }
2339
2340
tbl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & tab3,const LogicVRegister & tab4,const LogicVRegister & ind)2341 LogicVRegister Simulator::tbl(VectorFormat vform,
2342 LogicVRegister dst,
2343 const LogicVRegister& tab,
2344 const LogicVRegister& tab2,
2345 const LogicVRegister& tab3,
2346 const LogicVRegister& tab4,
2347 const LogicVRegister& ind) {
2348 SimVRegister result;
2349 movi(vform, result, 0);
2350 tbx(vform, result, tab, tab2, tab3, tab4, ind);
2351 return orr(vform, dst, result, result);
2352 }
2353
2354
tbx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & ind)2355 LogicVRegister Simulator::tbx(VectorFormat vform,
2356 LogicVRegister dst,
2357 const LogicVRegister& tab,
2358 const LogicVRegister& ind) {
2359 dst.ClearForWrite(vform);
2360 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2361 uint64_t j = ind.Uint(vform, i);
2362 switch (j >> 4) {
2363 case 0: dst.SetUint(vform, i, tab.Uint(kFormat16B, j & 15)); break;
2364 }
2365 }
2366 return dst;
2367 }
2368
2369
tbx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & ind)2370 LogicVRegister Simulator::tbx(VectorFormat vform,
2371 LogicVRegister dst,
2372 const LogicVRegister& tab,
2373 const LogicVRegister& tab2,
2374 const LogicVRegister& ind) {
2375 dst.ClearForWrite(vform);
2376 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2377 uint64_t j = ind.Uint(vform, i);
2378 switch (j >> 4) {
2379 case 0: dst.SetUint(vform, i, tab.Uint(kFormat16B, j & 15)); break;
2380 case 1: dst.SetUint(vform, i, tab2.Uint(kFormat16B, j & 15)); break;
2381 }
2382 }
2383 return dst;
2384 }
2385
2386
tbx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & tab3,const LogicVRegister & ind)2387 LogicVRegister Simulator::tbx(VectorFormat vform,
2388 LogicVRegister dst,
2389 const LogicVRegister& tab,
2390 const LogicVRegister& tab2,
2391 const LogicVRegister& tab3,
2392 const LogicVRegister& ind) {
2393 dst.ClearForWrite(vform);
2394 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2395 uint64_t j = ind.Uint(vform, i);
2396 switch (j >> 4) {
2397 case 0: dst.SetUint(vform, i, tab.Uint(kFormat16B, j & 15)); break;
2398 case 1: dst.SetUint(vform, i, tab2.Uint(kFormat16B, j & 15)); break;
2399 case 2: dst.SetUint(vform, i, tab3.Uint(kFormat16B, j & 15)); break;
2400 }
2401 }
2402 return dst;
2403 }
2404
2405
tbx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & tab,const LogicVRegister & tab2,const LogicVRegister & tab3,const LogicVRegister & tab4,const LogicVRegister & ind)2406 LogicVRegister Simulator::tbx(VectorFormat vform,
2407 LogicVRegister dst,
2408 const LogicVRegister& tab,
2409 const LogicVRegister& tab2,
2410 const LogicVRegister& tab3,
2411 const LogicVRegister& tab4,
2412 const LogicVRegister& ind) {
2413 dst.ClearForWrite(vform);
2414 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2415 uint64_t j = ind.Uint(vform, i);
2416 switch (j >> 4) {
2417 case 0: dst.SetUint(vform, i, tab.Uint(kFormat16B, j & 15)); break;
2418 case 1: dst.SetUint(vform, i, tab2.Uint(kFormat16B, j & 15)); break;
2419 case 2: dst.SetUint(vform, i, tab3.Uint(kFormat16B, j & 15)); break;
2420 case 3: dst.SetUint(vform, i, tab4.Uint(kFormat16B, j & 15)); break;
2421 }
2422 }
2423 return dst;
2424 }
2425
2426
uqshrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2427 LogicVRegister Simulator::uqshrn(VectorFormat vform,
2428 LogicVRegister dst,
2429 const LogicVRegister& src,
2430 int shift) {
2431 return shrn(vform, dst, src, shift).UnsignedSaturate(vform);
2432 }
2433
2434
uqshrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2435 LogicVRegister Simulator::uqshrn2(VectorFormat vform,
2436 LogicVRegister dst,
2437 const LogicVRegister& src,
2438 int shift) {
2439 return shrn2(vform, dst, src, shift).UnsignedSaturate(vform);
2440 }
2441
2442
uqrshrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2443 LogicVRegister Simulator::uqrshrn(VectorFormat vform,
2444 LogicVRegister dst,
2445 const LogicVRegister& src,
2446 int shift) {
2447 return rshrn(vform, dst, src, shift).UnsignedSaturate(vform);
2448 }
2449
2450
uqrshrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2451 LogicVRegister Simulator::uqrshrn2(VectorFormat vform,
2452 LogicVRegister dst,
2453 const LogicVRegister& src,
2454 int shift) {
2455 return rshrn2(vform, dst, src, shift).UnsignedSaturate(vform);
2456 }
2457
2458
sqshrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2459 LogicVRegister Simulator::sqshrn(VectorFormat vform,
2460 LogicVRegister dst,
2461 const LogicVRegister& src,
2462 int shift) {
2463 SimVRegister temp;
2464 VectorFormat vformsrc = VectorFormatDoubleWidth(vform);
2465 VectorFormat vformdst = vform;
2466 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift);
2467 return sqxtn(vformdst, dst, shifted_src);
2468 }
2469
2470
sqshrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2471 LogicVRegister Simulator::sqshrn2(VectorFormat vform,
2472 LogicVRegister dst,
2473 const LogicVRegister& src,
2474 int shift) {
2475 SimVRegister temp;
2476 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2477 VectorFormat vformdst = vform;
2478 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift);
2479 return sqxtn(vformdst, dst, shifted_src);
2480 }
2481
2482
sqrshrn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2483 LogicVRegister Simulator::sqrshrn(VectorFormat vform,
2484 LogicVRegister dst,
2485 const LogicVRegister& src,
2486 int shift) {
2487 SimVRegister temp;
2488 VectorFormat vformsrc = VectorFormatDoubleWidth(vform);
2489 VectorFormat vformdst = vform;
2490 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift).Round(vformsrc);
2491 return sqxtn(vformdst, dst, shifted_src);
2492 }
2493
2494
sqrshrn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2495 LogicVRegister Simulator::sqrshrn2(VectorFormat vform,
2496 LogicVRegister dst,
2497 const LogicVRegister& src,
2498 int shift) {
2499 SimVRegister temp;
2500 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2501 VectorFormat vformdst = vform;
2502 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift).Round(vformsrc);
2503 return sqxtn(vformdst, dst, shifted_src);
2504 }
2505
2506
sqshrun(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2507 LogicVRegister Simulator::sqshrun(VectorFormat vform,
2508 LogicVRegister dst,
2509 const LogicVRegister& src,
2510 int shift) {
2511 SimVRegister temp;
2512 VectorFormat vformsrc = VectorFormatDoubleWidth(vform);
2513 VectorFormat vformdst = vform;
2514 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift);
2515 return sqxtun(vformdst, dst, shifted_src);
2516 }
2517
2518
sqshrun2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2519 LogicVRegister Simulator::sqshrun2(VectorFormat vform,
2520 LogicVRegister dst,
2521 const LogicVRegister& src,
2522 int shift) {
2523 SimVRegister temp;
2524 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2525 VectorFormat vformdst = vform;
2526 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift);
2527 return sqxtun(vformdst, dst, shifted_src);
2528 }
2529
2530
sqrshrun(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2531 LogicVRegister Simulator::sqrshrun(VectorFormat vform,
2532 LogicVRegister dst,
2533 const LogicVRegister& src,
2534 int shift) {
2535 SimVRegister temp;
2536 VectorFormat vformsrc = VectorFormatDoubleWidth(vform);
2537 VectorFormat vformdst = vform;
2538 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift).Round(vformsrc);
2539 return sqxtun(vformdst, dst, shifted_src);
2540 }
2541
2542
sqrshrun2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int shift)2543 LogicVRegister Simulator::sqrshrun2(VectorFormat vform,
2544 LogicVRegister dst,
2545 const LogicVRegister& src,
2546 int shift) {
2547 SimVRegister temp;
2548 VectorFormat vformsrc = VectorFormatDoubleWidth(VectorFormatHalfLanes(vform));
2549 VectorFormat vformdst = vform;
2550 LogicVRegister shifted_src = sshr(vformsrc, temp, src, shift).Round(vformsrc);
2551 return sqxtun(vformdst, dst, shifted_src);
2552 }
2553
2554
uaddl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2555 LogicVRegister Simulator::uaddl(VectorFormat vform,
2556 LogicVRegister dst,
2557 const LogicVRegister& src1,
2558 const LogicVRegister& src2) {
2559 SimVRegister temp1, temp2;
2560 uxtl(vform, temp1, src1);
2561 uxtl(vform, temp2, src2);
2562 add(vform, dst, temp1, temp2);
2563 return dst;
2564 }
2565
2566
uaddl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2567 LogicVRegister Simulator::uaddl2(VectorFormat vform,
2568 LogicVRegister dst,
2569 const LogicVRegister& src1,
2570 const LogicVRegister& src2) {
2571 SimVRegister temp1, temp2;
2572 uxtl2(vform, temp1, src1);
2573 uxtl2(vform, temp2, src2);
2574 add(vform, dst, temp1, temp2);
2575 return dst;
2576 }
2577
2578
uaddw(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2579 LogicVRegister Simulator::uaddw(VectorFormat vform,
2580 LogicVRegister dst,
2581 const LogicVRegister& src1,
2582 const LogicVRegister& src2) {
2583 SimVRegister temp;
2584 uxtl(vform, temp, src2);
2585 add(vform, dst, src1, temp);
2586 return dst;
2587 }
2588
2589
uaddw2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2590 LogicVRegister Simulator::uaddw2(VectorFormat vform,
2591 LogicVRegister dst,
2592 const LogicVRegister& src1,
2593 const LogicVRegister& src2) {
2594 SimVRegister temp;
2595 uxtl2(vform, temp, src2);
2596 add(vform, dst, src1, temp);
2597 return dst;
2598 }
2599
2600
saddl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2601 LogicVRegister Simulator::saddl(VectorFormat vform,
2602 LogicVRegister dst,
2603 const LogicVRegister& src1,
2604 const LogicVRegister& src2) {
2605 SimVRegister temp1, temp2;
2606 sxtl(vform, temp1, src1);
2607 sxtl(vform, temp2, src2);
2608 add(vform, dst, temp1, temp2);
2609 return dst;
2610 }
2611
2612
saddl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2613 LogicVRegister Simulator::saddl2(VectorFormat vform,
2614 LogicVRegister dst,
2615 const LogicVRegister& src1,
2616 const LogicVRegister& src2) {
2617 SimVRegister temp1, temp2;
2618 sxtl2(vform, temp1, src1);
2619 sxtl2(vform, temp2, src2);
2620 add(vform, dst, temp1, temp2);
2621 return dst;
2622 }
2623
2624
saddw(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2625 LogicVRegister Simulator::saddw(VectorFormat vform,
2626 LogicVRegister dst,
2627 const LogicVRegister& src1,
2628 const LogicVRegister& src2) {
2629 SimVRegister temp;
2630 sxtl(vform, temp, src2);
2631 add(vform, dst, src1, temp);
2632 return dst;
2633 }
2634
2635
saddw2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2636 LogicVRegister Simulator::saddw2(VectorFormat vform,
2637 LogicVRegister dst,
2638 const LogicVRegister& src1,
2639 const LogicVRegister& src2) {
2640 SimVRegister temp;
2641 sxtl2(vform, temp, src2);
2642 add(vform, dst, src1, temp);
2643 return dst;
2644 }
2645
2646
usubl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2647 LogicVRegister Simulator::usubl(VectorFormat vform,
2648 LogicVRegister dst,
2649 const LogicVRegister& src1,
2650 const LogicVRegister& src2) {
2651 SimVRegister temp1, temp2;
2652 uxtl(vform, temp1, src1);
2653 uxtl(vform, temp2, src2);
2654 sub(vform, dst, temp1, temp2);
2655 return dst;
2656 }
2657
2658
usubl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2659 LogicVRegister Simulator::usubl2(VectorFormat vform,
2660 LogicVRegister dst,
2661 const LogicVRegister& src1,
2662 const LogicVRegister& src2) {
2663 SimVRegister temp1, temp2;
2664 uxtl2(vform, temp1, src1);
2665 uxtl2(vform, temp2, src2);
2666 sub(vform, dst, temp1, temp2);
2667 return dst;
2668 }
2669
2670
usubw(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2671 LogicVRegister Simulator::usubw(VectorFormat vform,
2672 LogicVRegister dst,
2673 const LogicVRegister& src1,
2674 const LogicVRegister& src2) {
2675 SimVRegister temp;
2676 uxtl(vform, temp, src2);
2677 sub(vform, dst, src1, temp);
2678 return dst;
2679 }
2680
2681
usubw2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2682 LogicVRegister Simulator::usubw2(VectorFormat vform,
2683 LogicVRegister dst,
2684 const LogicVRegister& src1,
2685 const LogicVRegister& src2) {
2686 SimVRegister temp;
2687 uxtl2(vform, temp, src2);
2688 sub(vform, dst, src1, temp);
2689 return dst;
2690 }
2691
2692
ssubl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2693 LogicVRegister Simulator::ssubl(VectorFormat vform,
2694 LogicVRegister dst,
2695 const LogicVRegister& src1,
2696 const LogicVRegister& src2) {
2697 SimVRegister temp1, temp2;
2698 sxtl(vform, temp1, src1);
2699 sxtl(vform, temp2, src2);
2700 sub(vform, dst, temp1, temp2);
2701 return dst;
2702 }
2703
2704
ssubl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2705 LogicVRegister Simulator::ssubl2(VectorFormat vform,
2706 LogicVRegister dst,
2707 const LogicVRegister& src1,
2708 const LogicVRegister& src2) {
2709 SimVRegister temp1, temp2;
2710 sxtl2(vform, temp1, src1);
2711 sxtl2(vform, temp2, src2);
2712 sub(vform, dst, temp1, temp2);
2713 return dst;
2714 }
2715
2716
ssubw(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2717 LogicVRegister Simulator::ssubw(VectorFormat vform,
2718 LogicVRegister dst,
2719 const LogicVRegister& src1,
2720 const LogicVRegister& src2) {
2721 SimVRegister temp;
2722 sxtl(vform, temp, src2);
2723 sub(vform, dst, src1, temp);
2724 return dst;
2725 }
2726
2727
ssubw2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2728 LogicVRegister Simulator::ssubw2(VectorFormat vform,
2729 LogicVRegister dst,
2730 const LogicVRegister& src1,
2731 const LogicVRegister& src2) {
2732 SimVRegister temp;
2733 sxtl2(vform, temp, src2);
2734 sub(vform, dst, src1, temp);
2735 return dst;
2736 }
2737
2738
uabal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2739 LogicVRegister Simulator::uabal(VectorFormat vform,
2740 LogicVRegister dst,
2741 const LogicVRegister& src1,
2742 const LogicVRegister& src2) {
2743 SimVRegister temp1, temp2;
2744 uxtl(vform, temp1, src1);
2745 uxtl(vform, temp2, src2);
2746 uaba(vform, dst, temp1, temp2);
2747 return dst;
2748 }
2749
2750
uabal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2751 LogicVRegister Simulator::uabal2(VectorFormat vform,
2752 LogicVRegister dst,
2753 const LogicVRegister& src1,
2754 const LogicVRegister& src2) {
2755 SimVRegister temp1, temp2;
2756 uxtl2(vform, temp1, src1);
2757 uxtl2(vform, temp2, src2);
2758 uaba(vform, dst, temp1, temp2);
2759 return dst;
2760 }
2761
2762
sabal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2763 LogicVRegister Simulator::sabal(VectorFormat vform,
2764 LogicVRegister dst,
2765 const LogicVRegister& src1,
2766 const LogicVRegister& src2) {
2767 SimVRegister temp1, temp2;
2768 sxtl(vform, temp1, src1);
2769 sxtl(vform, temp2, src2);
2770 saba(vform, dst, temp1, temp2);
2771 return dst;
2772 }
2773
2774
sabal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2775 LogicVRegister Simulator::sabal2(VectorFormat vform,
2776 LogicVRegister dst,
2777 const LogicVRegister& src1,
2778 const LogicVRegister& src2) {
2779 SimVRegister temp1, temp2;
2780 sxtl2(vform, temp1, src1);
2781 sxtl2(vform, temp2, src2);
2782 saba(vform, dst, temp1, temp2);
2783 return dst;
2784 }
2785
2786
uabdl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2787 LogicVRegister Simulator::uabdl(VectorFormat vform,
2788 LogicVRegister dst,
2789 const LogicVRegister& src1,
2790 const LogicVRegister& src2) {
2791 SimVRegister temp1, temp2;
2792 uxtl(vform, temp1, src1);
2793 uxtl(vform, temp2, src2);
2794 absdiff(vform, dst, temp1, temp2, false);
2795 return dst;
2796 }
2797
2798
uabdl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2799 LogicVRegister Simulator::uabdl2(VectorFormat vform,
2800 LogicVRegister dst,
2801 const LogicVRegister& src1,
2802 const LogicVRegister& src2) {
2803 SimVRegister temp1, temp2;
2804 uxtl2(vform, temp1, src1);
2805 uxtl2(vform, temp2, src2);
2806 absdiff(vform, dst, temp1, temp2, false);
2807 return dst;
2808 }
2809
2810
sabdl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2811 LogicVRegister Simulator::sabdl(VectorFormat vform,
2812 LogicVRegister dst,
2813 const LogicVRegister& src1,
2814 const LogicVRegister& src2) {
2815 SimVRegister temp1, temp2;
2816 sxtl(vform, temp1, src1);
2817 sxtl(vform, temp2, src2);
2818 absdiff(vform, dst, temp1, temp2, true);
2819 return dst;
2820 }
2821
2822
sabdl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2823 LogicVRegister Simulator::sabdl2(VectorFormat vform,
2824 LogicVRegister dst,
2825 const LogicVRegister& src1,
2826 const LogicVRegister& src2) {
2827 SimVRegister temp1, temp2;
2828 sxtl2(vform, temp1, src1);
2829 sxtl2(vform, temp2, src2);
2830 absdiff(vform, dst, temp1, temp2, true);
2831 return dst;
2832 }
2833
2834
umull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2835 LogicVRegister Simulator::umull(VectorFormat vform,
2836 LogicVRegister dst,
2837 const LogicVRegister& src1,
2838 const LogicVRegister& src2) {
2839 SimVRegister temp1, temp2;
2840 uxtl(vform, temp1, src1);
2841 uxtl(vform, temp2, src2);
2842 mul(vform, dst, temp1, temp2);
2843 return dst;
2844 }
2845
2846
umull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2847 LogicVRegister Simulator::umull2(VectorFormat vform,
2848 LogicVRegister dst,
2849 const LogicVRegister& src1,
2850 const LogicVRegister& src2) {
2851 SimVRegister temp1, temp2;
2852 uxtl2(vform, temp1, src1);
2853 uxtl2(vform, temp2, src2);
2854 mul(vform, dst, temp1, temp2);
2855 return dst;
2856 }
2857
2858
smull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2859 LogicVRegister Simulator::smull(VectorFormat vform,
2860 LogicVRegister dst,
2861 const LogicVRegister& src1,
2862 const LogicVRegister& src2) {
2863 SimVRegister temp1, temp2;
2864 sxtl(vform, temp1, src1);
2865 sxtl(vform, temp2, src2);
2866 mul(vform, dst, temp1, temp2);
2867 return dst;
2868 }
2869
2870
smull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2871 LogicVRegister Simulator::smull2(VectorFormat vform,
2872 LogicVRegister dst,
2873 const LogicVRegister& src1,
2874 const LogicVRegister& src2) {
2875 SimVRegister temp1, temp2;
2876 sxtl2(vform, temp1, src1);
2877 sxtl2(vform, temp2, src2);
2878 mul(vform, dst, temp1, temp2);
2879 return dst;
2880 }
2881
2882
umlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2883 LogicVRegister Simulator::umlsl(VectorFormat vform,
2884 LogicVRegister dst,
2885 const LogicVRegister& src1,
2886 const LogicVRegister& src2) {
2887 SimVRegister temp1, temp2;
2888 uxtl(vform, temp1, src1);
2889 uxtl(vform, temp2, src2);
2890 mls(vform, dst, temp1, temp2);
2891 return dst;
2892 }
2893
2894
umlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2895 LogicVRegister Simulator::umlsl2(VectorFormat vform,
2896 LogicVRegister dst,
2897 const LogicVRegister& src1,
2898 const LogicVRegister& src2) {
2899 SimVRegister temp1, temp2;
2900 uxtl2(vform, temp1, src1);
2901 uxtl2(vform, temp2, src2);
2902 mls(vform, dst, temp1, temp2);
2903 return dst;
2904 }
2905
2906
smlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2907 LogicVRegister Simulator::smlsl(VectorFormat vform,
2908 LogicVRegister dst,
2909 const LogicVRegister& src1,
2910 const LogicVRegister& src2) {
2911 SimVRegister temp1, temp2;
2912 sxtl(vform, temp1, src1);
2913 sxtl(vform, temp2, src2);
2914 mls(vform, dst, temp1, temp2);
2915 return dst;
2916 }
2917
2918
smlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2919 LogicVRegister Simulator::smlsl2(VectorFormat vform,
2920 LogicVRegister dst,
2921 const LogicVRegister& src1,
2922 const LogicVRegister& src2) {
2923 SimVRegister temp1, temp2;
2924 sxtl2(vform, temp1, src1);
2925 sxtl2(vform, temp2, src2);
2926 mls(vform, dst, temp1, temp2);
2927 return dst;
2928 }
2929
2930
umlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2931 LogicVRegister Simulator::umlal(VectorFormat vform,
2932 LogicVRegister dst,
2933 const LogicVRegister& src1,
2934 const LogicVRegister& src2) {
2935 SimVRegister temp1, temp2;
2936 uxtl(vform, temp1, src1);
2937 uxtl(vform, temp2, src2);
2938 mla(vform, dst, temp1, temp2);
2939 return dst;
2940 }
2941
2942
umlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2943 LogicVRegister Simulator::umlal2(VectorFormat vform,
2944 LogicVRegister dst,
2945 const LogicVRegister& src1,
2946 const LogicVRegister& src2) {
2947 SimVRegister temp1, temp2;
2948 uxtl2(vform, temp1, src1);
2949 uxtl2(vform, temp2, src2);
2950 mla(vform, dst, temp1, temp2);
2951 return dst;
2952 }
2953
2954
smlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2955 LogicVRegister Simulator::smlal(VectorFormat vform,
2956 LogicVRegister dst,
2957 const LogicVRegister& src1,
2958 const LogicVRegister& src2) {
2959 SimVRegister temp1, temp2;
2960 sxtl(vform, temp1, src1);
2961 sxtl(vform, temp2, src2);
2962 mla(vform, dst, temp1, temp2);
2963 return dst;
2964 }
2965
2966
smlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2967 LogicVRegister Simulator::smlal2(VectorFormat vform,
2968 LogicVRegister dst,
2969 const LogicVRegister& src1,
2970 const LogicVRegister& src2) {
2971 SimVRegister temp1, temp2;
2972 sxtl2(vform, temp1, src1);
2973 sxtl2(vform, temp2, src2);
2974 mla(vform, dst, temp1, temp2);
2975 return dst;
2976 }
2977
2978
sqdmlal(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2979 LogicVRegister Simulator::sqdmlal(VectorFormat vform,
2980 LogicVRegister dst,
2981 const LogicVRegister& src1,
2982 const LogicVRegister& src2) {
2983 SimVRegister temp;
2984 LogicVRegister product = sqdmull(vform, temp, src1, src2);
2985 return add(vform, dst, dst, product).SignedSaturate(vform);
2986 }
2987
2988
sqdmlal2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2989 LogicVRegister Simulator::sqdmlal2(VectorFormat vform,
2990 LogicVRegister dst,
2991 const LogicVRegister& src1,
2992 const LogicVRegister& src2) {
2993 SimVRegister temp;
2994 LogicVRegister product = sqdmull2(vform, temp, src1, src2);
2995 return add(vform, dst, dst, product).SignedSaturate(vform);
2996 }
2997
2998
sqdmlsl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)2999 LogicVRegister Simulator::sqdmlsl(VectorFormat vform,
3000 LogicVRegister dst,
3001 const LogicVRegister& src1,
3002 const LogicVRegister& src2) {
3003 SimVRegister temp;
3004 LogicVRegister product = sqdmull(vform, temp, src1, src2);
3005 return sub(vform, dst, dst, product).SignedSaturate(vform);
3006 }
3007
3008
sqdmlsl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3009 LogicVRegister Simulator::sqdmlsl2(VectorFormat vform,
3010 LogicVRegister dst,
3011 const LogicVRegister& src1,
3012 const LogicVRegister& src2) {
3013 SimVRegister temp;
3014 LogicVRegister product = sqdmull2(vform, temp, src1, src2);
3015 return sub(vform, dst, dst, product).SignedSaturate(vform);
3016 }
3017
3018
sqdmull(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3019 LogicVRegister Simulator::sqdmull(VectorFormat vform,
3020 LogicVRegister dst,
3021 const LogicVRegister& src1,
3022 const LogicVRegister& src2) {
3023 SimVRegister temp;
3024 LogicVRegister product = smull(vform, temp, src1, src2);
3025 return add(vform, dst, product, product).SignedSaturate(vform);
3026 }
3027
3028
sqdmull2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3029 LogicVRegister Simulator::sqdmull2(VectorFormat vform,
3030 LogicVRegister dst,
3031 const LogicVRegister& src1,
3032 const LogicVRegister& src2) {
3033 SimVRegister temp;
3034 LogicVRegister product = smull2(vform, temp, src1, src2);
3035 return add(vform, dst, product, product).SignedSaturate(vform);
3036 }
3037
3038
sqrdmulh(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,bool round)3039 LogicVRegister Simulator::sqrdmulh(VectorFormat vform,
3040 LogicVRegister dst,
3041 const LogicVRegister& src1,
3042 const LogicVRegister& src2,
3043 bool round) {
3044 // 2 * INT_32_MIN * INT_32_MIN causes int64_t to overflow.
3045 // To avoid this, we use (src1 * src2 + 1 << (esize - 2)) >> (esize - 1)
3046 // which is same as (2 * src1 * src2 + 1 << (esize - 1)) >> esize.
3047
3048 int esize = LaneSizeInBitsFromFormat(vform);
3049 int round_const = round ? (1 << (esize - 2)) : 0;
3050 int64_t product;
3051
3052 dst.ClearForWrite(vform);
3053 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3054 product = src1.Int(vform, i) * src2.Int(vform, i);
3055 product += round_const;
3056 product = product >> (esize - 1);
3057
3058 if (product > MaxIntFromFormat(vform)) {
3059 product = MaxIntFromFormat(vform);
3060 } else if (product < MinIntFromFormat(vform)) {
3061 product = MinIntFromFormat(vform);
3062 }
3063 dst.SetInt(vform, i, product);
3064 }
3065 return dst;
3066 }
3067
3068
sqdmulh(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3069 LogicVRegister Simulator::sqdmulh(VectorFormat vform,
3070 LogicVRegister dst,
3071 const LogicVRegister& src1,
3072 const LogicVRegister& src2) {
3073 return sqrdmulh(vform, dst, src1, src2, false);
3074 }
3075
3076
addhn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3077 LogicVRegister Simulator::addhn(VectorFormat vform,
3078 LogicVRegister dst,
3079 const LogicVRegister& src1,
3080 const LogicVRegister& src2) {
3081 SimVRegister temp;
3082 add(VectorFormatDoubleWidth(vform), temp, src1, src2);
3083 shrn(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3084 return dst;
3085 }
3086
3087
addhn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3088 LogicVRegister Simulator::addhn2(VectorFormat vform,
3089 LogicVRegister dst,
3090 const LogicVRegister& src1,
3091 const LogicVRegister& src2) {
3092 SimVRegister temp;
3093 add(VectorFormatDoubleWidth(VectorFormatHalfLanes(vform)), temp, src1, src2);
3094 shrn2(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3095 return dst;
3096 }
3097
3098
raddhn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3099 LogicVRegister Simulator::raddhn(VectorFormat vform,
3100 LogicVRegister dst,
3101 const LogicVRegister& src1,
3102 const LogicVRegister& src2) {
3103 SimVRegister temp;
3104 add(VectorFormatDoubleWidth(vform), temp, src1, src2);
3105 rshrn(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3106 return dst;
3107 }
3108
3109
raddhn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3110 LogicVRegister Simulator::raddhn2(VectorFormat vform,
3111 LogicVRegister dst,
3112 const LogicVRegister& src1,
3113 const LogicVRegister& src2) {
3114 SimVRegister temp;
3115 add(VectorFormatDoubleWidth(VectorFormatHalfLanes(vform)), temp, src1, src2);
3116 rshrn2(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3117 return dst;
3118 }
3119
3120
subhn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3121 LogicVRegister Simulator::subhn(VectorFormat vform,
3122 LogicVRegister dst,
3123 const LogicVRegister& src1,
3124 const LogicVRegister& src2) {
3125 SimVRegister temp;
3126 sub(VectorFormatDoubleWidth(vform), temp, src1, src2);
3127 shrn(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3128 return dst;
3129 }
3130
3131
subhn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3132 LogicVRegister Simulator::subhn2(VectorFormat vform,
3133 LogicVRegister dst,
3134 const LogicVRegister& src1,
3135 const LogicVRegister& src2) {
3136 SimVRegister temp;
3137 sub(VectorFormatDoubleWidth(VectorFormatHalfLanes(vform)), temp, src1, src2);
3138 shrn2(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3139 return dst;
3140 }
3141
3142
rsubhn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3143 LogicVRegister Simulator::rsubhn(VectorFormat vform,
3144 LogicVRegister dst,
3145 const LogicVRegister& src1,
3146 const LogicVRegister& src2) {
3147 SimVRegister temp;
3148 sub(VectorFormatDoubleWidth(vform), temp, src1, src2);
3149 rshrn(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3150 return dst;
3151 }
3152
3153
rsubhn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3154 LogicVRegister Simulator::rsubhn2(VectorFormat vform,
3155 LogicVRegister dst,
3156 const LogicVRegister& src1,
3157 const LogicVRegister& src2) {
3158 SimVRegister temp;
3159 sub(VectorFormatDoubleWidth(VectorFormatHalfLanes(vform)), temp, src1, src2);
3160 rshrn2(vform, dst, temp, LaneSizeInBitsFromFormat(vform));
3161 return dst;
3162 }
3163
3164
trn1(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3165 LogicVRegister Simulator::trn1(VectorFormat vform,
3166 LogicVRegister dst,
3167 const LogicVRegister& src1,
3168 const LogicVRegister& src2) {
3169 uint64_t result[16];
3170 int laneCount = LaneCountFromFormat(vform);
3171 int pairs = laneCount / 2;
3172 for (int i = 0; i < pairs; ++i) {
3173 result[2 * i] = src1.Uint(vform, 2 * i);
3174 result[(2 * i) + 1] = src2.Uint(vform, 2 * i);
3175 }
3176
3177 dst.ClearForWrite(vform);
3178 for (int i = 0; i < laneCount; ++i) {
3179 dst.SetUint(vform, i, result[i]);
3180 }
3181 return dst;
3182 }
3183
3184
trn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3185 LogicVRegister Simulator::trn2(VectorFormat vform,
3186 LogicVRegister dst,
3187 const LogicVRegister& src1,
3188 const LogicVRegister& src2) {
3189 uint64_t result[16];
3190 int laneCount = LaneCountFromFormat(vform);
3191 int pairs = laneCount / 2;
3192 for (int i = 0; i < pairs; ++i) {
3193 result[2 * i] = src1.Uint(vform, (2 * i) + 1);
3194 result[(2 * i) + 1] = src2.Uint(vform, (2 * i) + 1);
3195 }
3196
3197 dst.ClearForWrite(vform);
3198 for (int i = 0; i < laneCount; ++i) {
3199 dst.SetUint(vform, i, result[i]);
3200 }
3201 return dst;
3202 }
3203
3204
zip1(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3205 LogicVRegister Simulator::zip1(VectorFormat vform,
3206 LogicVRegister dst,
3207 const LogicVRegister& src1,
3208 const LogicVRegister& src2) {
3209 uint64_t result[16];
3210 int laneCount = LaneCountFromFormat(vform);
3211 int pairs = laneCount / 2;
3212 for (int i = 0; i < pairs; ++i) {
3213 result[2 * i] = src1.Uint(vform, i);
3214 result[(2 * i) + 1] = src2.Uint(vform, i);
3215 }
3216
3217 dst.ClearForWrite(vform);
3218 for (int i = 0; i < laneCount; ++i) {
3219 dst.SetUint(vform, i, result[i]);
3220 }
3221 return dst;
3222 }
3223
3224
zip2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3225 LogicVRegister Simulator::zip2(VectorFormat vform,
3226 LogicVRegister dst,
3227 const LogicVRegister& src1,
3228 const LogicVRegister& src2) {
3229 uint64_t result[16];
3230 int laneCount = LaneCountFromFormat(vform);
3231 int pairs = laneCount / 2;
3232 for (int i = 0; i < pairs; ++i) {
3233 result[2 * i] = src1.Uint(vform, pairs + i);
3234 result[(2 * i) + 1] = src2.Uint(vform, pairs + i);
3235 }
3236
3237 dst.ClearForWrite(vform);
3238 for (int i = 0; i < laneCount; ++i) {
3239 dst.SetUint(vform, i, result[i]);
3240 }
3241 return dst;
3242 }
3243
3244
uzp1(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3245 LogicVRegister Simulator::uzp1(VectorFormat vform,
3246 LogicVRegister dst,
3247 const LogicVRegister& src1,
3248 const LogicVRegister& src2) {
3249 uint64_t result[32];
3250 int laneCount = LaneCountFromFormat(vform);
3251 for (int i = 0; i < laneCount; ++i) {
3252 result[i] = src1.Uint(vform, i);
3253 result[laneCount + i] = src2.Uint(vform, i);
3254 }
3255
3256 dst.ClearForWrite(vform);
3257 for (int i = 0; i < laneCount; ++i) {
3258 dst.SetUint(vform, i, result[2 * i]);
3259 }
3260 return dst;
3261 }
3262
3263
uzp2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3264 LogicVRegister Simulator::uzp2(VectorFormat vform,
3265 LogicVRegister dst,
3266 const LogicVRegister& src1,
3267 const LogicVRegister& src2) {
3268 uint64_t result[32];
3269 int laneCount = LaneCountFromFormat(vform);
3270 for (int i = 0; i < laneCount; ++i) {
3271 result[i] = src1.Uint(vform, i);
3272 result[laneCount + i] = src2.Uint(vform, i);
3273 }
3274
3275 dst.ClearForWrite(vform);
3276 for (int i = 0; i < laneCount; ++i) {
3277 dst.SetUint(vform, i, result[ (2 * i) + 1]);
3278 }
3279 return dst;
3280 }
3281
3282
3283 template <typename T>
FPAdd(T op1,T op2)3284 T Simulator::FPAdd(T op1, T op2) {
3285 T result = FPProcessNaNs(op1, op2);
3286 if (std::isnan(result)) return result;
3287
3288 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
3289 // inf + -inf returns the default NaN.
3290 FPProcessException();
3291 return FPDefaultNaN<T>();
3292 } else {
3293 // Other cases should be handled by standard arithmetic.
3294 return op1 + op2;
3295 }
3296 }
3297
3298
3299 template <typename T>
FPSub(T op1,T op2)3300 T Simulator::FPSub(T op1, T op2) {
3301 // NaNs should be handled elsewhere.
3302 VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
3303
3304 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3305 // inf - inf returns the default NaN.
3306 FPProcessException();
3307 return FPDefaultNaN<T>();
3308 } else {
3309 // Other cases should be handled by standard arithmetic.
3310 return op1 - op2;
3311 }
3312 }
3313
3314
3315 template <typename T>
FPMul(T op1,T op2)3316 T Simulator::FPMul(T op1, T op2) {
3317 // NaNs should be handled elsewhere.
3318 VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
3319
3320 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3321 // inf * 0.0 returns the default NaN.
3322 FPProcessException();
3323 return FPDefaultNaN<T>();
3324 } else {
3325 // Other cases should be handled by standard arithmetic.
3326 return op1 * op2;
3327 }
3328 }
3329
3330
3331 template<typename T>
FPMulx(T op1,T op2)3332 T Simulator::FPMulx(T op1, T op2) {
3333 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3334 // inf * 0.0 returns +/-2.0.
3335 T two = 2.0;
3336 return copysign(1.0, op1) * copysign(1.0, op2) * two;
3337 }
3338 return FPMul(op1, op2);
3339 }
3340
3341
3342 template<typename T>
FPMulAdd(T a,T op1,T op2)3343 T Simulator::FPMulAdd(T a, T op1, T op2) {
3344 T result = FPProcessNaNs3(a, op1, op2);
3345
3346 T sign_a = copysign(1.0, a);
3347 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
3348 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
3349 bool operation_generates_nan =
3350 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
3351 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
3352 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
3353
3354 if (std::isnan(result)) {
3355 // Generated NaNs override quiet NaNs propagated from a.
3356 if (operation_generates_nan && IsQuietNaN(a)) {
3357 FPProcessException();
3358 return FPDefaultNaN<T>();
3359 } else {
3360 return result;
3361 }
3362 }
3363
3364 // If the operation would produce a NaN, return the default NaN.
3365 if (operation_generates_nan) {
3366 FPProcessException();
3367 return FPDefaultNaN<T>();
3368 }
3369
3370 // Work around broken fma implementations for exact zero results: The sign of
3371 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
3372 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
3373 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
3374 }
3375
3376 result = FusedMultiplyAdd(op1, op2, a);
3377 VIXL_ASSERT(!std::isnan(result));
3378
3379 // Work around broken fma implementations for rounded zero results: If a is
3380 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
3381 if ((a == 0.0) && (result == 0.0)) {
3382 return copysign(0.0, sign_prod);
3383 }
3384
3385 return result;
3386 }
3387
3388
3389 template <typename T>
FPDiv(T op1,T op2)3390 T Simulator::FPDiv(T op1, T op2) {
3391 // NaNs should be handled elsewhere.
3392 VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
3393
3394 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
3395 // inf / inf and 0.0 / 0.0 return the default NaN.
3396 FPProcessException();
3397 return FPDefaultNaN<T>();
3398 } else {
3399 if (op2 == 0.0) FPProcessException();
3400
3401 // Other cases should be handled by standard arithmetic.
3402 return op1 / op2;
3403 }
3404 }
3405
3406
3407 template <typename T>
FPSqrt(T op)3408 T Simulator::FPSqrt(T op) {
3409 if (std::isnan(op)) {
3410 return FPProcessNaN(op);
3411 } else if (op < 0.0) {
3412 FPProcessException();
3413 return FPDefaultNaN<T>();
3414 } else {
3415 return sqrt(op);
3416 }
3417 }
3418
3419
3420 template <typename T>
FPMax(T a,T b)3421 T Simulator::FPMax(T a, T b) {
3422 T result = FPProcessNaNs(a, b);
3423 if (std::isnan(result)) return result;
3424
3425 if ((a == 0.0) && (b == 0.0) &&
3426 (copysign(1.0, a) != copysign(1.0, b))) {
3427 // a and b are zero, and the sign differs: return +0.0.
3428 return 0.0;
3429 } else {
3430 return (a > b) ? a : b;
3431 }
3432 }
3433
3434
3435 template <typename T>
FPMaxNM(T a,T b)3436 T Simulator::FPMaxNM(T a, T b) {
3437 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3438 a = kFP64NegativeInfinity;
3439 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3440 b = kFP64NegativeInfinity;
3441 }
3442
3443 T result = FPProcessNaNs(a, b);
3444 return std::isnan(result) ? result : FPMax(a, b);
3445 }
3446
3447
3448 template <typename T>
FPMin(T a,T b)3449 T Simulator::FPMin(T a, T b) {
3450 T result = FPProcessNaNs(a, b);
3451 if (std::isnan(result)) return result;
3452
3453 if ((a == 0.0) && (b == 0.0) &&
3454 (copysign(1.0, a) != copysign(1.0, b))) {
3455 // a and b are zero, and the sign differs: return -0.0.
3456 return -0.0;
3457 } else {
3458 return (a < b) ? a : b;
3459 }
3460 }
3461
3462
3463 template <typename T>
FPMinNM(T a,T b)3464 T Simulator::FPMinNM(T a, T b) {
3465 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3466 a = kFP64PositiveInfinity;
3467 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3468 b = kFP64PositiveInfinity;
3469 }
3470
3471 T result = FPProcessNaNs(a, b);
3472 return std::isnan(result) ? result : FPMin(a, b);
3473 }
3474
3475
3476 template <typename T>
FPRecipStepFused(T op1,T op2)3477 T Simulator::FPRecipStepFused(T op1, T op2) {
3478 const T two = 2.0;
3479 if ((std::isinf(op1) && (op2 == 0.0))
3480 || ((op1 == 0.0) && (std::isinf(op2)))) {
3481 return two;
3482 } else if (std::isinf(op1) || std::isinf(op2)) {
3483 // Return +inf if signs match, otherwise -inf.
3484 return ((op1 >= 0.0) == (op2 >= 0.0)) ? kFP64PositiveInfinity
3485 : kFP64NegativeInfinity;
3486 } else {
3487 return FusedMultiplyAdd(op1, op2, two);
3488 }
3489 }
3490
3491
3492 template <typename T>
FPRSqrtStepFused(T op1,T op2)3493 T Simulator::FPRSqrtStepFused(T op1, T op2) {
3494 const T one_point_five = 1.5;
3495 const T two = 2.0;
3496
3497 if ((std::isinf(op1) && (op2 == 0.0))
3498 || ((op1 == 0.0) && (std::isinf(op2)))) {
3499 return one_point_five;
3500 } else if (std::isinf(op1) || std::isinf(op2)) {
3501 // Return +inf if signs match, otherwise -inf.
3502 return ((op1 >= 0.0) == (op2 >= 0.0)) ? kFP64PositiveInfinity
3503 : kFP64NegativeInfinity;
3504 } else {
3505 // The multiply-add-halve operation must be fully fused, so avoid interim
3506 // rounding by checking which operand can be losslessly divided by two
3507 // before doing the multiply-add.
3508 if (std::isnormal(op1 / two)) {
3509 return FusedMultiplyAdd(op1 / two, op2, one_point_five);
3510 } else if (std::isnormal(op2 / two)) {
3511 return FusedMultiplyAdd(op1, op2 / two, one_point_five);
3512 } else {
3513 // Neither operand is normal after halving: the result is dominated by
3514 // the addition term, so just return that.
3515 return one_point_five;
3516 }
3517 }
3518 }
3519
FPToFixedJS(double value)3520 int32_t Simulator::FPToFixedJS(double value) {
3521 // The Z-flag is set when the conversion from double precision floating-point
3522 // to 32-bit integer is exact. If the source value is +/-Infinity, -0.0, NaN,
3523 // outside the bounds of a 32-bit integer, or isn't an exact integer then the
3524 // Z-flag is unset.
3525 int Z = 1;
3526 int32_t result;
3527
3528 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
3529 (value == kFP64NegativeInfinity)) {
3530 // +/- zero and infinity all return zero, however -0 and +/- Infinity also
3531 // unset the Z-flag.
3532 result = 0.0;
3533 if ((value != 0.0) || std::signbit(value)) {
3534 Z = 0;
3535 }
3536 } else if (std::isnan(value)) {
3537 // NaN values unset the Z-flag and set the result to 0.
3538 FPProcessNaN(value);
3539 result = 0;
3540 Z = 0;
3541 } else {
3542 // All other values are converted to an integer representation, rounded
3543 // toward zero.
3544 double int_result = std::floor(value);
3545 double error = value - int_result;
3546
3547 if ((error != 0.0) && (int_result < 0.0)) {
3548 int_result++;
3549 }
3550
3551 // Constrain the value into the range [INT32_MIN, INT32_MAX]. We can almost
3552 // write a one-liner with std::round, but the behaviour on ties is incorrect
3553 // for our purposes.
3554 double mod_const = static_cast<double>(UINT64_C(1) << 32);
3555 double mod_error =
3556 (int_result / mod_const) - std::floor(int_result / mod_const);
3557 double constrained;
3558 if (mod_error == 0.5) {
3559 constrained = INT32_MIN;
3560 } else {
3561 constrained = int_result - mod_const * round(int_result / mod_const);
3562 }
3563
3564 VIXL_ASSERT(std::floor(constrained) == constrained);
3565 VIXL_ASSERT(constrained >= INT32_MIN);
3566 VIXL_ASSERT(constrained <= INT32_MAX);
3567
3568 // Take the bottom 32 bits of the result as a 32-bit integer.
3569 result = static_cast<int32_t>(constrained);
3570
3571 if ((int_result < INT32_MIN) || (int_result > INT32_MAX) ||
3572 (error != 0.0)) {
3573 // If the integer result is out of range or the conversion isn't exact,
3574 // take exception and unset the Z-flag.
3575 FPProcessException();
3576 Z = 0;
3577 }
3578 }
3579
3580 ReadNzcv().SetN(0);
3581 ReadNzcv().SetZ(Z);
3582 ReadNzcv().SetC(0);
3583 ReadNzcv().SetV(0);
3584
3585 return result;
3586 }
3587
3588
FPRoundInt(double value,FPRounding round_mode)3589 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
3590 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
3591 (value == kFP64NegativeInfinity)) {
3592 return value;
3593 } else if (std::isnan(value)) {
3594 return FPProcessNaN(value);
3595 }
3596
3597 double int_result = std::floor(value);
3598 double error = value - int_result;
3599 switch (round_mode) {
3600 case FPTieAway: {
3601 // Take care of correctly handling the range ]-0.5, -0.0], which must
3602 // yield -0.0.
3603 if ((-0.5 < value) && (value < 0.0)) {
3604 int_result = -0.0;
3605
3606 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
3607 // If the error is greater than 0.5, or is equal to 0.5 and the integer
3608 // result is positive, round up.
3609 int_result++;
3610 }
3611 break;
3612 }
3613 case FPTieEven: {
3614 // Take care of correctly handling the range [-0.5, -0.0], which must
3615 // yield -0.0.
3616 if ((-0.5 <= value) && (value < 0.0)) {
3617 int_result = -0.0;
3618
3619 // If the error is greater than 0.5, or is equal to 0.5 and the integer
3620 // result is odd, round up.
3621 } else if ((error > 0.5) ||
3622 ((error == 0.5) && (std::fmod(int_result, 2) != 0))) {
3623 int_result++;
3624 }
3625 break;
3626 }
3627 case FPZero: {
3628 // If value>0 then we take floor(value)
3629 // otherwise, ceil(value).
3630 if (value < 0) {
3631 int_result = ceil(value);
3632 }
3633 break;
3634 }
3635 case FPNegativeInfinity: {
3636 // We always use floor(value).
3637 break;
3638 }
3639 case FPPositiveInfinity: {
3640 // Take care of correctly handling the range ]-1.0, -0.0], which must
3641 // yield -0.0.
3642 if ((-1.0 < value) && (value < 0.0)) {
3643 int_result = -0.0;
3644
3645 // If the error is non-zero, round up.
3646 } else if (error > 0.0) {
3647 int_result++;
3648 }
3649 break;
3650 }
3651 default: VIXL_UNIMPLEMENTED();
3652 }
3653 return int_result;
3654 }
3655
3656
FPToInt32(double value,FPRounding rmode)3657 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
3658 value = FPRoundInt(value, rmode);
3659 if (value >= kWMaxInt) {
3660 return kWMaxInt;
3661 } else if (value < kWMinInt) {
3662 return kWMinInt;
3663 }
3664 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
3665 }
3666
3667
FPToInt64(double value,FPRounding rmode)3668 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
3669 value = FPRoundInt(value, rmode);
3670 // The compiler would have to round kXMaxInt, triggering a warning. Compare
3671 // against the largest int64_t that is exactly representable as a double.
3672 if (value > kXMaxExactInt) {
3673 return kXMaxInt;
3674 } else if (value < kXMinInt) {
3675 return kXMinInt;
3676 }
3677 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
3678 }
3679
3680
FPToUInt32(double value,FPRounding rmode)3681 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
3682 value = FPRoundInt(value, rmode);
3683 if (value >= kWMaxUInt) {
3684 return kWMaxUInt;
3685 } else if (value < 0.0) {
3686 return 0;
3687 }
3688 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
3689 }
3690
3691
FPToUInt64(double value,FPRounding rmode)3692 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
3693 value = FPRoundInt(value, rmode);
3694 // The compiler would have to round kXMaxUInt, triggering a warning. Compare
3695 // against the largest uint64_t that is exactly representable as a double.
3696 if (value > kXMaxExactUInt) {
3697 return kXMaxUInt;
3698 } else if (value < 0.0) {
3699 return 0;
3700 }
3701 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
3702 }
3703
3704
3705 #define DEFINE_NEON_FP_VECTOR_OP(FN, OP, PROCNAN) \
3706 template <typename T> \
3707 LogicVRegister Simulator::FN(VectorFormat vform, \
3708 LogicVRegister dst, \
3709 const LogicVRegister& src1, \
3710 const LogicVRegister& src2) { \
3711 dst.ClearForWrite(vform); \
3712 for (int i = 0; i < LaneCountFromFormat(vform); i++) { \
3713 T op1 = src1.Float<T>(i); \
3714 T op2 = src2.Float<T>(i); \
3715 T result; \
3716 if (PROCNAN) { \
3717 result = FPProcessNaNs(op1, op2); \
3718 if (!std::isnan(result)) { \
3719 result = OP(op1, op2); \
3720 } \
3721 } else { \
3722 result = OP(op1, op2); \
3723 } \
3724 dst.SetFloat(i, result); \
3725 } \
3726 return dst; \
3727 } \
3728 \
3729 LogicVRegister Simulator::FN(VectorFormat vform, \
3730 LogicVRegister dst, \
3731 const LogicVRegister& src1, \
3732 const LogicVRegister& src2) { \
3733 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) { \
3734 FN<float>(vform, dst, src1, src2); \
3735 } else { \
3736 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize); \
3737 FN<double>(vform, dst, src1, src2); \
3738 } \
3739 return dst; \
3740 }
NEON_FP3SAME_LIST(DEFINE_NEON_FP_VECTOR_OP)3741 NEON_FP3SAME_LIST(DEFINE_NEON_FP_VECTOR_OP)
3742 #undef DEFINE_NEON_FP_VECTOR_OP
3743
3744
3745 LogicVRegister Simulator::fnmul(VectorFormat vform,
3746 LogicVRegister dst,
3747 const LogicVRegister& src1,
3748 const LogicVRegister& src2) {
3749 SimVRegister temp;
3750 LogicVRegister product = fmul(vform, temp, src1, src2);
3751 return fneg(vform, dst, product);
3752 }
3753
3754
3755 template <typename T>
frecps(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3756 LogicVRegister Simulator::frecps(VectorFormat vform,
3757 LogicVRegister dst,
3758 const LogicVRegister& src1,
3759 const LogicVRegister& src2) {
3760 dst.ClearForWrite(vform);
3761 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3762 T op1 = -src1.Float<T>(i);
3763 T op2 = src2.Float<T>(i);
3764 T result = FPProcessNaNs(op1, op2);
3765 dst.SetFloat(i, std::isnan(result) ? result : FPRecipStepFused(op1, op2));
3766 }
3767 return dst;
3768 }
3769
3770
frecps(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3771 LogicVRegister Simulator::frecps(VectorFormat vform,
3772 LogicVRegister dst,
3773 const LogicVRegister& src1,
3774 const LogicVRegister& src2) {
3775 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3776 frecps<float>(vform, dst, src1, src2);
3777 } else {
3778 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3779 frecps<double>(vform, dst, src1, src2);
3780 }
3781 return dst;
3782 }
3783
3784
3785 template <typename T>
frsqrts(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3786 LogicVRegister Simulator::frsqrts(VectorFormat vform,
3787 LogicVRegister dst,
3788 const LogicVRegister& src1,
3789 const LogicVRegister& src2) {
3790 dst.ClearForWrite(vform);
3791 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3792 T op1 = -src1.Float<T>(i);
3793 T op2 = src2.Float<T>(i);
3794 T result = FPProcessNaNs(op1, op2);
3795 dst.SetFloat(i, std::isnan(result) ? result : FPRSqrtStepFused(op1, op2));
3796 }
3797 return dst;
3798 }
3799
3800
frsqrts(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3801 LogicVRegister Simulator::frsqrts(VectorFormat vform,
3802 LogicVRegister dst,
3803 const LogicVRegister& src1,
3804 const LogicVRegister& src2) {
3805 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3806 frsqrts<float>(vform, dst, src1, src2);
3807 } else {
3808 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3809 frsqrts<double>(vform, dst, src1, src2);
3810 }
3811 return dst;
3812 }
3813
3814
3815 template <typename T>
fcmp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,Condition cond)3816 LogicVRegister Simulator::fcmp(VectorFormat vform,
3817 LogicVRegister dst,
3818 const LogicVRegister& src1,
3819 const LogicVRegister& src2,
3820 Condition cond) {
3821 dst.ClearForWrite(vform);
3822 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3823 bool result = false;
3824 T op1 = src1.Float<T>(i);
3825 T op2 = src2.Float<T>(i);
3826 T nan_result = FPProcessNaNs(op1, op2);
3827 if (!std::isnan(nan_result)) {
3828 switch (cond) {
3829 case eq: result = (op1 == op2); break;
3830 case ge: result = (op1 >= op2); break;
3831 case gt: result = (op1 > op2) ; break;
3832 case le: result = (op1 <= op2); break;
3833 case lt: result = (op1 < op2) ; break;
3834 default: VIXL_UNREACHABLE(); break;
3835 }
3836 }
3837 dst.SetUint(vform, i, result ? MaxUintFromFormat(vform) : 0);
3838 }
3839 return dst;
3840 }
3841
3842
fcmp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,Condition cond)3843 LogicVRegister Simulator::fcmp(VectorFormat vform,
3844 LogicVRegister dst,
3845 const LogicVRegister& src1,
3846 const LogicVRegister& src2,
3847 Condition cond) {
3848 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3849 fcmp<float>(vform, dst, src1, src2, cond);
3850 } else {
3851 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3852 fcmp<double>(vform, dst, src1, src2, cond);
3853 }
3854 return dst;
3855 }
3856
3857
fcmp_zero(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,Condition cond)3858 LogicVRegister Simulator::fcmp_zero(VectorFormat vform,
3859 LogicVRegister dst,
3860 const LogicVRegister& src,
3861 Condition cond) {
3862 SimVRegister temp;
3863 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3864 LogicVRegister zero_reg = dup_immediate(vform, temp, FloatToRawbits(0.0));
3865 fcmp<float>(vform, dst, src, zero_reg, cond);
3866 } else {
3867 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3868 LogicVRegister zero_reg = dup_immediate(vform, temp,
3869 DoubleToRawbits(0.0));
3870 fcmp<double>(vform, dst, src, zero_reg, cond);
3871 }
3872 return dst;
3873 }
3874
3875
fabscmp(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,Condition cond)3876 LogicVRegister Simulator::fabscmp(VectorFormat vform,
3877 LogicVRegister dst,
3878 const LogicVRegister& src1,
3879 const LogicVRegister& src2,
3880 Condition cond) {
3881 SimVRegister temp1, temp2;
3882 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3883 LogicVRegister abs_src1 = fabs_<float>(vform, temp1, src1);
3884 LogicVRegister abs_src2 = fabs_<float>(vform, temp2, src2);
3885 fcmp<float>(vform, dst, abs_src1, abs_src2, cond);
3886 } else {
3887 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3888 LogicVRegister abs_src1 = fabs_<double>(vform, temp1, src1);
3889 LogicVRegister abs_src2 = fabs_<double>(vform, temp2, src2);
3890 fcmp<double>(vform, dst, abs_src1, abs_src2, cond);
3891 }
3892 return dst;
3893 }
3894
3895
3896 template <typename T>
fmla(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3897 LogicVRegister Simulator::fmla(VectorFormat vform,
3898 LogicVRegister dst,
3899 const LogicVRegister& src1,
3900 const LogicVRegister& src2) {
3901 dst.ClearForWrite(vform);
3902 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3903 T op1 = src1.Float<T>(i);
3904 T op2 = src2.Float<T>(i);
3905 T acc = dst.Float<T>(i);
3906 T result = FPMulAdd(acc, op1, op2);
3907 dst.SetFloat(i, result);
3908 }
3909 return dst;
3910 }
3911
3912
fmla(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3913 LogicVRegister Simulator::fmla(VectorFormat vform,
3914 LogicVRegister dst,
3915 const LogicVRegister& src1,
3916 const LogicVRegister& src2) {
3917 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3918 fmla<float>(vform, dst, src1, src2);
3919 } else {
3920 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3921 fmla<double>(vform, dst, src1, src2);
3922 }
3923 return dst;
3924 }
3925
3926
3927 template <typename T>
fmls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3928 LogicVRegister Simulator::fmls(VectorFormat vform,
3929 LogicVRegister dst,
3930 const LogicVRegister& src1,
3931 const LogicVRegister& src2) {
3932 dst.ClearForWrite(vform);
3933 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3934 T op1 = -src1.Float<T>(i);
3935 T op2 = src2.Float<T>(i);
3936 T acc = dst.Float<T>(i);
3937 T result = FPMulAdd(acc, op1, op2);
3938 dst.SetFloat(i, result);
3939 }
3940 return dst;
3941 }
3942
3943
fmls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)3944 LogicVRegister Simulator::fmls(VectorFormat vform,
3945 LogicVRegister dst,
3946 const LogicVRegister& src1,
3947 const LogicVRegister& src2) {
3948 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3949 fmls<float>(vform, dst, src1, src2);
3950 } else {
3951 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3952 fmls<double>(vform, dst, src1, src2);
3953 }
3954 return dst;
3955 }
3956
3957
3958 template <typename T>
fneg(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)3959 LogicVRegister Simulator::fneg(VectorFormat vform,
3960 LogicVRegister dst,
3961 const LogicVRegister& src) {
3962 dst.ClearForWrite(vform);
3963 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3964 T op = src.Float<T>(i);
3965 op = -op;
3966 dst.SetFloat(i, op);
3967 }
3968 return dst;
3969 }
3970
3971
fneg(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)3972 LogicVRegister Simulator::fneg(VectorFormat vform,
3973 LogicVRegister dst,
3974 const LogicVRegister& src) {
3975 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
3976 fneg<float>(vform, dst, src);
3977 } else {
3978 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
3979 fneg<double>(vform, dst, src);
3980 }
3981 return dst;
3982 }
3983
3984
3985 template <typename T>
fabs_(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)3986 LogicVRegister Simulator::fabs_(VectorFormat vform,
3987 LogicVRegister dst,
3988 const LogicVRegister& src) {
3989 dst.ClearForWrite(vform);
3990 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
3991 T op = src.Float<T>(i);
3992 if (copysign(1.0, op) < 0.0) {
3993 op = -op;
3994 }
3995 dst.SetFloat(i, op);
3996 }
3997 return dst;
3998 }
3999
4000
fabs_(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4001 LogicVRegister Simulator::fabs_(VectorFormat vform,
4002 LogicVRegister dst,
4003 const LogicVRegister& src) {
4004 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4005 fabs_<float>(vform, dst, src);
4006 } else {
4007 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4008 fabs_<double>(vform, dst, src);
4009 }
4010 return dst;
4011 }
4012
4013
fabd(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2)4014 LogicVRegister Simulator::fabd(VectorFormat vform,
4015 LogicVRegister dst,
4016 const LogicVRegister& src1,
4017 const LogicVRegister& src2) {
4018 SimVRegister temp;
4019 fsub(vform, temp, src1, src2);
4020 fabs_(vform, dst, temp);
4021 return dst;
4022 }
4023
4024
fsqrt(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4025 LogicVRegister Simulator::fsqrt(VectorFormat vform,
4026 LogicVRegister dst,
4027 const LogicVRegister& src) {
4028 dst.ClearForWrite(vform);
4029 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4030 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4031 float result = FPSqrt(src.Float<float>(i));
4032 dst.SetFloat(i, result);
4033 }
4034 } else {
4035 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4036 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4037 double result = FPSqrt(src.Float<double>(i));
4038 dst.SetFloat(i, result);
4039 }
4040 }
4041 return dst;
4042 }
4043
4044
4045 #define DEFINE_NEON_FP_PAIR_OP(FNP, FN, OP) \
4046 LogicVRegister Simulator::FNP(VectorFormat vform, \
4047 LogicVRegister dst, \
4048 const LogicVRegister& src1, \
4049 const LogicVRegister& src2) { \
4050 SimVRegister temp1, temp2; \
4051 uzp1(vform, temp1, src1, src2); \
4052 uzp2(vform, temp2, src1, src2); \
4053 FN(vform, dst, temp1, temp2); \
4054 return dst; \
4055 } \
4056 \
4057 LogicVRegister Simulator::FNP(VectorFormat vform, \
4058 LogicVRegister dst, \
4059 const LogicVRegister& src) { \
4060 if (vform == kFormatS) { \
4061 float result = OP(src.Float<float>(0), src.Float<float>(1)); \
4062 dst.SetFloat(0, result); \
4063 } else { \
4064 VIXL_ASSERT(vform == kFormatD); \
4065 double result = OP(src.Float<double>(0), src.Float<double>(1)); \
4066 dst.SetFloat(0, result); \
4067 } \
4068 dst.ClearForWrite(vform); \
4069 return dst; \
4070 }
NEON_FPPAIRWISE_LIST(DEFINE_NEON_FP_PAIR_OP)4071 NEON_FPPAIRWISE_LIST(DEFINE_NEON_FP_PAIR_OP)
4072 #undef DEFINE_NEON_FP_PAIR_OP
4073
4074
4075 LogicVRegister Simulator::fminmaxv(VectorFormat vform,
4076 LogicVRegister dst,
4077 const LogicVRegister& src,
4078 FPMinMaxOp Op) {
4079 VIXL_ASSERT(vform == kFormat4S);
4080 USE(vform);
4081 float result1 = (this->*Op)(src.Float<float>(0), src.Float<float>(1));
4082 float result2 = (this->*Op)(src.Float<float>(2), src.Float<float>(3));
4083 float result = (this->*Op)(result1, result2);
4084 dst.ClearForWrite(kFormatS);
4085 dst.SetFloat<float>(0, result);
4086 return dst;
4087 }
4088
4089
fmaxv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4090 LogicVRegister Simulator::fmaxv(VectorFormat vform,
4091 LogicVRegister dst,
4092 const LogicVRegister& src) {
4093 return fminmaxv(vform, dst, src, &Simulator::FPMax);
4094 }
4095
4096
fminv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4097 LogicVRegister Simulator::fminv(VectorFormat vform,
4098 LogicVRegister dst,
4099 const LogicVRegister& src) {
4100 return fminmaxv(vform, dst, src, &Simulator::FPMin);
4101 }
4102
4103
fmaxnmv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4104 LogicVRegister Simulator::fmaxnmv(VectorFormat vform,
4105 LogicVRegister dst,
4106 const LogicVRegister& src) {
4107 return fminmaxv(vform, dst, src, &Simulator::FPMaxNM);
4108 }
4109
4110
fminnmv(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4111 LogicVRegister Simulator::fminnmv(VectorFormat vform,
4112 LogicVRegister dst,
4113 const LogicVRegister& src) {
4114 return fminmaxv(vform, dst, src, &Simulator::FPMinNM);
4115 }
4116
4117
fmul(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)4118 LogicVRegister Simulator::fmul(VectorFormat vform,
4119 LogicVRegister dst,
4120 const LogicVRegister& src1,
4121 const LogicVRegister& src2,
4122 int index) {
4123 dst.ClearForWrite(vform);
4124 SimVRegister temp;
4125 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4126 LogicVRegister index_reg = dup_element(kFormat4S, temp, src2, index);
4127 fmul<float>(vform, dst, src1, index_reg);
4128
4129 } else {
4130 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4131 LogicVRegister index_reg = dup_element(kFormat2D, temp, src2, index);
4132 fmul<double>(vform, dst, src1, index_reg);
4133 }
4134 return dst;
4135 }
4136
4137
fmla(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)4138 LogicVRegister Simulator::fmla(VectorFormat vform,
4139 LogicVRegister dst,
4140 const LogicVRegister& src1,
4141 const LogicVRegister& src2,
4142 int index) {
4143 dst.ClearForWrite(vform);
4144 SimVRegister temp;
4145 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4146 LogicVRegister index_reg = dup_element(kFormat4S, temp, src2, index);
4147 fmla<float>(vform, dst, src1, index_reg);
4148
4149 } else {
4150 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4151 LogicVRegister index_reg = dup_element(kFormat2D, temp, src2, index);
4152 fmla<double>(vform, dst, src1, index_reg);
4153 }
4154 return dst;
4155 }
4156
4157
fmls(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)4158 LogicVRegister Simulator::fmls(VectorFormat vform,
4159 LogicVRegister dst,
4160 const LogicVRegister& src1,
4161 const LogicVRegister& src2,
4162 int index) {
4163 dst.ClearForWrite(vform);
4164 SimVRegister temp;
4165 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4166 LogicVRegister index_reg = dup_element(kFormat4S, temp, src2, index);
4167 fmls<float>(vform, dst, src1, index_reg);
4168
4169 } else {
4170 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4171 LogicVRegister index_reg = dup_element(kFormat2D, temp, src2, index);
4172 fmls<double>(vform, dst, src1, index_reg);
4173 }
4174 return dst;
4175 }
4176
4177
fmulx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src1,const LogicVRegister & src2,int index)4178 LogicVRegister Simulator::fmulx(VectorFormat vform,
4179 LogicVRegister dst,
4180 const LogicVRegister& src1,
4181 const LogicVRegister& src2,
4182 int index) {
4183 dst.ClearForWrite(vform);
4184 SimVRegister temp;
4185 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4186 LogicVRegister index_reg = dup_element(kFormat4S, temp, src2, index);
4187 fmulx<float>(vform, dst, src1, index_reg);
4188
4189 } else {
4190 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4191 LogicVRegister index_reg = dup_element(kFormat2D, temp, src2, index);
4192 fmulx<double>(vform, dst, src1, index_reg);
4193 }
4194 return dst;
4195 }
4196
4197
frint(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,FPRounding rounding_mode,bool inexact_exception)4198 LogicVRegister Simulator::frint(VectorFormat vform,
4199 LogicVRegister dst,
4200 const LogicVRegister& src,
4201 FPRounding rounding_mode,
4202 bool inexact_exception) {
4203 dst.ClearForWrite(vform);
4204 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4205 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4206 float input = src.Float<float>(i);
4207 float rounded = FPRoundInt(input, rounding_mode);
4208 if (inexact_exception && !std::isnan(input) && (input != rounded)) {
4209 FPProcessException();
4210 }
4211 dst.SetFloat<float>(i, rounded);
4212 }
4213 } else {
4214 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4215 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4216 double input = src.Float<double>(i);
4217 double rounded = FPRoundInt(input, rounding_mode);
4218 if (inexact_exception && !std::isnan(input) && (input != rounded)) {
4219 FPProcessException();
4220 }
4221 dst.SetFloat<double>(i, rounded);
4222 }
4223 }
4224 return dst;
4225 }
4226
4227
fcvts(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,FPRounding rounding_mode,int fbits)4228 LogicVRegister Simulator::fcvts(VectorFormat vform,
4229 LogicVRegister dst,
4230 const LogicVRegister& src,
4231 FPRounding rounding_mode,
4232 int fbits) {
4233 dst.ClearForWrite(vform);
4234 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4235 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4236 float op = src.Float<float>(i) * std::pow(2.0f, fbits);
4237 dst.SetInt(vform, i, FPToInt32(op, rounding_mode));
4238 }
4239 } else {
4240 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4241 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4242 double op = src.Float<double>(i) * std::pow(2.0, fbits);
4243 dst.SetInt(vform, i, FPToInt64(op, rounding_mode));
4244 }
4245 }
4246 return dst;
4247 }
4248
4249
fcvtu(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,FPRounding rounding_mode,int fbits)4250 LogicVRegister Simulator::fcvtu(VectorFormat vform,
4251 LogicVRegister dst,
4252 const LogicVRegister& src,
4253 FPRounding rounding_mode,
4254 int fbits) {
4255 dst.ClearForWrite(vform);
4256 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4257 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4258 float op = src.Float<float>(i) * std::pow(2.0f, fbits);
4259 dst.SetUint(vform, i, FPToUInt32(op, rounding_mode));
4260 }
4261 } else {
4262 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4263 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4264 double op = src.Float<double>(i) * std::pow(2.0, fbits);
4265 dst.SetUint(vform, i, FPToUInt64(op, rounding_mode));
4266 }
4267 }
4268 return dst;
4269 }
4270
4271
fcvtl(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4272 LogicVRegister Simulator::fcvtl(VectorFormat vform,
4273 LogicVRegister dst,
4274 const LogicVRegister& src) {
4275 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4276 for (int i = LaneCountFromFormat(vform) - 1; i >= 0; i--) {
4277 // TODO: Full support for SimFloat16 in SimRegister(s).
4278 dst.SetFloat(i,
4279 FPToFloat(RawbitsToFloat16(src.Float<uint16_t>(i)),
4280 ReadDN()));
4281 }
4282 } else {
4283 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4284 for (int i = LaneCountFromFormat(vform) - 1; i >= 0; i--) {
4285 dst.SetFloat(i, FPToDouble(src.Float<float>(i), ReadDN()));
4286 }
4287 }
4288 return dst;
4289 }
4290
4291
fcvtl2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4292 LogicVRegister Simulator::fcvtl2(VectorFormat vform,
4293 LogicVRegister dst,
4294 const LogicVRegister& src) {
4295 int lane_count = LaneCountFromFormat(vform);
4296 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4297 for (int i = 0; i < lane_count; i++) {
4298 // TODO: Full support for SimFloat16 in SimRegister(s).
4299 dst.SetFloat(i,
4300 FPToFloat(RawbitsToFloat16(
4301 src.Float<uint16_t>(i + lane_count)),
4302 ReadDN()));
4303 }
4304 } else {
4305 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4306 for (int i = 0; i < lane_count; i++) {
4307 dst.SetFloat(i, FPToDouble(src.Float<float>(i + lane_count), ReadDN()));
4308 }
4309 }
4310 return dst;
4311 }
4312
4313
fcvtn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4314 LogicVRegister Simulator::fcvtn(VectorFormat vform,
4315 LogicVRegister dst,
4316 const LogicVRegister& src) {
4317 SimVRegister tmp;
4318 LogicVRegister srctmp = mov(kFormat2D, tmp, src);
4319 dst.ClearForWrite(vform);
4320 if (LaneSizeInBitsFromFormat(vform) == kHRegSize) {
4321 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4322 dst.SetFloat(i,
4323 Float16ToRawbits(FPToFloat16(srctmp.Float<float>(i),
4324 FPTieEven,
4325 ReadDN())));
4326 }
4327 } else {
4328 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kSRegSize);
4329 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4330 dst.SetFloat(i, FPToFloat(srctmp.Float<double>(i), FPTieEven, ReadDN()));
4331 }
4332 }
4333 return dst;
4334 }
4335
4336
fcvtn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4337 LogicVRegister Simulator::fcvtn2(VectorFormat vform,
4338 LogicVRegister dst,
4339 const LogicVRegister& src) {
4340 int lane_count = LaneCountFromFormat(vform) / 2;
4341 if (LaneSizeInBitsFromFormat(vform) == kHRegSize) {
4342 for (int i = lane_count - 1; i >= 0; i--) {
4343 dst.SetFloat(i + lane_count,
4344 Float16ToRawbits(
4345 FPToFloat16(src.Float<float>(i), FPTieEven, ReadDN())));
4346 }
4347 } else {
4348 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kSRegSize);
4349 for (int i = lane_count - 1; i >= 0; i--) {
4350 dst.SetFloat(i + lane_count,
4351 FPToFloat(src.Float<double>(i), FPTieEven, ReadDN()));
4352 }
4353 }
4354 return dst;
4355 }
4356
4357
fcvtxn(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4358 LogicVRegister Simulator::fcvtxn(VectorFormat vform,
4359 LogicVRegister dst,
4360 const LogicVRegister& src) {
4361 SimVRegister tmp;
4362 LogicVRegister srctmp = mov(kFormat2D, tmp, src);
4363 dst.ClearForWrite(vform);
4364 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kSRegSize);
4365 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4366 dst.SetFloat(i, FPToFloat(srctmp.Float<double>(i), FPRoundOdd, ReadDN()));
4367 }
4368 return dst;
4369 }
4370
4371
fcvtxn2(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4372 LogicVRegister Simulator::fcvtxn2(VectorFormat vform,
4373 LogicVRegister dst,
4374 const LogicVRegister& src) {
4375 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kSRegSize);
4376 int lane_count = LaneCountFromFormat(vform) / 2;
4377 for (int i = lane_count - 1; i >= 0; i--) {
4378 dst.SetFloat(i + lane_count,
4379 FPToFloat(src.Float<double>(i), FPRoundOdd, ReadDN()));
4380 }
4381 return dst;
4382 }
4383
4384
4385 // Based on reference C function recip_sqrt_estimate from ARM ARM.
recip_sqrt_estimate(double a)4386 double Simulator::recip_sqrt_estimate(double a) {
4387 int q0, q1, s;
4388 double r;
4389 if (a < 0.5) {
4390 q0 = static_cast<int>(a * 512.0);
4391 r = 1.0 / sqrt((static_cast<double>(q0) + 0.5) / 512.0);
4392 } else {
4393 q1 = static_cast<int>(a * 256.0);
4394 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0);
4395 }
4396 s = static_cast<int>(256.0 * r + 0.5);
4397 return static_cast<double>(s) / 256.0;
4398 }
4399
4400
Bits(uint64_t val,int start_bit,int end_bit)4401 static inline uint64_t Bits(uint64_t val, int start_bit, int end_bit) {
4402 return ExtractUnsignedBitfield64(start_bit, end_bit, val);
4403 }
4404
4405
4406 template <typename T>
FPRecipSqrtEstimate(T op)4407 T Simulator::FPRecipSqrtEstimate(T op) {
4408 if (std::isnan(op)) {
4409 return FPProcessNaN(op);
4410 } else if (op == 0.0) {
4411 if (copysign(1.0, op) < 0.0) {
4412 return kFP64NegativeInfinity;
4413 } else {
4414 return kFP64PositiveInfinity;
4415 }
4416 } else if (copysign(1.0, op) < 0.0) {
4417 FPProcessException();
4418 return FPDefaultNaN<T>();
4419 } else if (std::isinf(op)) {
4420 return 0.0;
4421 } else {
4422 uint64_t fraction;
4423 int exp, result_exp;
4424
4425 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4426 exp = FloatExp(op);
4427 fraction = FloatMantissa(op);
4428 fraction <<= 29;
4429 } else {
4430 exp = DoubleExp(op);
4431 fraction = DoubleMantissa(op);
4432 }
4433
4434 if (exp == 0) {
4435 while (Bits(fraction, 51, 51) == 0) {
4436 fraction = Bits(fraction, 50, 0) << 1;
4437 exp -= 1;
4438 }
4439 fraction = Bits(fraction, 50, 0) << 1;
4440 }
4441
4442 double scaled;
4443 if (Bits(exp, 0, 0) == 0) {
4444 scaled = DoublePack(0, 1022, Bits(fraction, 51, 44) << 44);
4445 } else {
4446 scaled = DoublePack(0, 1021, Bits(fraction, 51, 44) << 44);
4447 }
4448
4449 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4450 result_exp = (380 - exp) / 2;
4451 } else {
4452 result_exp = (3068 - exp) / 2;
4453 }
4454
4455 uint64_t estimate = DoubleToRawbits(recip_sqrt_estimate(scaled));
4456
4457 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4458 uint32_t exp_bits = static_cast<uint32_t>(Bits(result_exp, 7, 0));
4459 uint32_t est_bits = static_cast<uint32_t>(Bits(estimate, 51, 29));
4460 return FloatPack(0, exp_bits, est_bits);
4461 } else {
4462 return DoublePack(0, Bits(result_exp, 10, 0), Bits(estimate, 51, 0));
4463 }
4464 }
4465 }
4466
4467
frsqrte(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4468 LogicVRegister Simulator::frsqrte(VectorFormat vform,
4469 LogicVRegister dst,
4470 const LogicVRegister& src) {
4471 dst.ClearForWrite(vform);
4472 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4473 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4474 float input = src.Float<float>(i);
4475 dst.SetFloat(i, FPRecipSqrtEstimate<float>(input));
4476 }
4477 } else {
4478 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4479 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4480 double input = src.Float<double>(i);
4481 dst.SetFloat(i, FPRecipSqrtEstimate<double>(input));
4482 }
4483 }
4484 return dst;
4485 }
4486
4487 template <typename T>
FPRecipEstimate(T op,FPRounding rounding)4488 T Simulator::FPRecipEstimate(T op, FPRounding rounding) {
4489 uint32_t sign;
4490
4491 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4492 sign = FloatSign(op);
4493 } else {
4494 sign = DoubleSign(op);
4495 }
4496
4497 if (std::isnan(op)) {
4498 return FPProcessNaN(op);
4499 } else if (std::isinf(op)) {
4500 return (sign == 1) ? -0.0 : 0.0;
4501 } else if (op == 0.0) {
4502 FPProcessException(); // FPExc_DivideByZero exception.
4503 return (sign == 1) ? kFP64NegativeInfinity : kFP64PositiveInfinity;
4504 } else if (((sizeof(T) == sizeof(float)) && // NOLINT(runtime/sizeof)
4505 (std::fabs(op) < std::pow(2.0, -128.0))) ||
4506 ((sizeof(T) == sizeof(double)) && // NOLINT(runtime/sizeof)
4507 (std::fabs(op) < std::pow(2.0, -1024.0)))) {
4508 bool overflow_to_inf = false;
4509 switch (rounding) {
4510 case FPTieEven: overflow_to_inf = true; break;
4511 case FPPositiveInfinity: overflow_to_inf = (sign == 0); break;
4512 case FPNegativeInfinity: overflow_to_inf = (sign == 1); break;
4513 case FPZero: overflow_to_inf = false; break;
4514 default: break;
4515 }
4516 FPProcessException(); // FPExc_Overflow and FPExc_Inexact.
4517 if (overflow_to_inf) {
4518 return (sign == 1) ? kFP64NegativeInfinity : kFP64PositiveInfinity;
4519 } else {
4520 // Return FPMaxNormal(sign).
4521 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4522 return FloatPack(sign, 0xfe, 0x07fffff);
4523 } else {
4524 return DoublePack(sign, 0x7fe, 0x0fffffffffffffl);
4525 }
4526 }
4527 } else {
4528 uint64_t fraction;
4529 int exp, result_exp;
4530 uint32_t sign;
4531
4532 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4533 sign = FloatSign(op);
4534 exp = FloatExp(op);
4535 fraction = FloatMantissa(op);
4536 fraction <<= 29;
4537 } else {
4538 sign = DoubleSign(op);
4539 exp = DoubleExp(op);
4540 fraction = DoubleMantissa(op);
4541 }
4542
4543 if (exp == 0) {
4544 if (Bits(fraction, 51, 51) == 0) {
4545 exp -= 1;
4546 fraction = Bits(fraction, 49, 0) << 2;
4547 } else {
4548 fraction = Bits(fraction, 50, 0) << 1;
4549 }
4550 }
4551
4552 double scaled = DoublePack(0, 1022, Bits(fraction, 51, 44) << 44);
4553
4554 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4555 result_exp = (253 - exp); // In range 253-254 = -1 to 253+1 = 254.
4556 } else {
4557 result_exp = (2045 - exp); // In range 2045-2046 = -1 to 2045+1 = 2046.
4558 }
4559
4560 double estimate = recip_estimate(scaled);
4561
4562 fraction = DoubleMantissa(estimate);
4563 if (result_exp == 0) {
4564 fraction = (UINT64_C(1) << 51) | Bits(fraction, 51, 1);
4565 } else if (result_exp == -1) {
4566 fraction = (UINT64_C(1) << 50) | Bits(fraction, 51, 2);
4567 result_exp = 0;
4568 }
4569 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4570 uint32_t exp_bits = static_cast<uint32_t>(Bits(result_exp, 7, 0));
4571 uint32_t frac_bits = static_cast<uint32_t>(Bits(fraction, 51, 29));
4572 return FloatPack(sign, exp_bits, frac_bits);
4573 } else {
4574 return DoublePack(sign, Bits(result_exp, 10, 0), Bits(fraction, 51, 0));
4575 }
4576 }
4577 }
4578
4579
frecpe(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,FPRounding round)4580 LogicVRegister Simulator::frecpe(VectorFormat vform,
4581 LogicVRegister dst,
4582 const LogicVRegister& src,
4583 FPRounding round) {
4584 dst.ClearForWrite(vform);
4585 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4586 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4587 float input = src.Float<float>(i);
4588 dst.SetFloat(i, FPRecipEstimate<float>(input, round));
4589 }
4590 } else {
4591 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4592 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4593 double input = src.Float<double>(i);
4594 dst.SetFloat(i, FPRecipEstimate<double>(input, round));
4595 }
4596 }
4597 return dst;
4598 }
4599
4600
ursqrte(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4601 LogicVRegister Simulator::ursqrte(VectorFormat vform,
4602 LogicVRegister dst,
4603 const LogicVRegister& src) {
4604 dst.ClearForWrite(vform);
4605 uint64_t operand;
4606 uint32_t result;
4607 double dp_operand, dp_result;
4608 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4609 operand = src.Uint(vform, i);
4610 if (operand <= 0x3FFFFFFF) {
4611 result = 0xFFFFFFFF;
4612 } else {
4613 dp_operand = operand * std::pow(2.0, -32);
4614 dp_result = recip_sqrt_estimate(dp_operand) * std::pow(2.0, 31);
4615 result = static_cast<uint32_t>(dp_result);
4616 }
4617 dst.SetUint(vform, i, result);
4618 }
4619 return dst;
4620 }
4621
4622
4623 // Based on reference C function recip_estimate from ARM ARM.
recip_estimate(double a)4624 double Simulator::recip_estimate(double a) {
4625 int q, s;
4626 double r;
4627 q = static_cast<int>(a * 512.0);
4628 r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0);
4629 s = static_cast<int>(256.0 * r + 0.5);
4630 return static_cast<double>(s) / 256.0;
4631 }
4632
4633
urecpe(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4634 LogicVRegister Simulator::urecpe(VectorFormat vform,
4635 LogicVRegister dst,
4636 const LogicVRegister& src) {
4637 dst.ClearForWrite(vform);
4638 uint64_t operand;
4639 uint32_t result;
4640 double dp_operand, dp_result;
4641 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4642 operand = src.Uint(vform, i);
4643 if (operand <= 0x7FFFFFFF) {
4644 result = 0xFFFFFFFF;
4645 } else {
4646 dp_operand = operand * std::pow(2.0, -32);
4647 dp_result = recip_estimate(dp_operand) * std::pow(2.0, 31);
4648 result = static_cast<uint32_t>(dp_result);
4649 }
4650 dst.SetUint(vform, i, result);
4651 }
4652 return dst;
4653 }
4654
4655 template <typename T>
frecpx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4656 LogicVRegister Simulator::frecpx(VectorFormat vform,
4657 LogicVRegister dst,
4658 const LogicVRegister& src) {
4659 dst.ClearForWrite(vform);
4660 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4661 T op = src.Float<T>(i);
4662 T result;
4663 if (std::isnan(op)) {
4664 result = FPProcessNaN(op);
4665 } else {
4666 int exp;
4667 uint32_t sign;
4668 if (sizeof(T) == sizeof(float)) { // NOLINT(runtime/sizeof)
4669 sign = FloatSign(op);
4670 exp = FloatExp(op);
4671 exp = (exp == 0) ? (0xFF - 1) : static_cast<int>(Bits(~exp, 7, 0));
4672 result = FloatPack(sign, exp, 0);
4673 } else {
4674 sign = DoubleSign(op);
4675 exp = DoubleExp(op);
4676 exp = (exp == 0) ? (0x7FF - 1) : static_cast<int>(Bits(~exp, 10, 0));
4677 result = DoublePack(sign, exp, 0);
4678 }
4679 }
4680 dst.SetFloat(i, result);
4681 }
4682 return dst;
4683 }
4684
4685
frecpx(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src)4686 LogicVRegister Simulator::frecpx(VectorFormat vform,
4687 LogicVRegister dst,
4688 const LogicVRegister& src) {
4689 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4690 frecpx<float>(vform, dst, src);
4691 } else {
4692 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4693 frecpx<double>(vform, dst, src);
4694 }
4695 return dst;
4696 }
4697
scvtf(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int fbits,FPRounding round)4698 LogicVRegister Simulator::scvtf(VectorFormat vform,
4699 LogicVRegister dst,
4700 const LogicVRegister& src,
4701 int fbits,
4702 FPRounding round) {
4703 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4704 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4705 float result = FixedToFloat(src.Int(kFormatS, i), fbits, round);
4706 dst.SetFloat<float>(i, result);
4707 } else {
4708 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4709 double result = FixedToDouble(src.Int(kFormatD, i), fbits, round);
4710 dst.SetFloat<double>(i, result);
4711 }
4712 }
4713 return dst;
4714 }
4715
4716
ucvtf(VectorFormat vform,LogicVRegister dst,const LogicVRegister & src,int fbits,FPRounding round)4717 LogicVRegister Simulator::ucvtf(VectorFormat vform,
4718 LogicVRegister dst,
4719 const LogicVRegister& src,
4720 int fbits,
4721 FPRounding round) {
4722 for (int i = 0; i < LaneCountFromFormat(vform); i++) {
4723 if (LaneSizeInBitsFromFormat(vform) == kSRegSize) {
4724 float result = UFixedToFloat(src.Uint(kFormatS, i), fbits, round);
4725 dst.SetFloat<float>(i, result);
4726 } else {
4727 VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kDRegSize);
4728 double result = UFixedToDouble(src.Uint(kFormatD, i), fbits, round);
4729 dst.SetFloat<double>(i, result);
4730 }
4731 }
4732 return dst;
4733 }
4734
4735
4736 } // namespace vixl
4737
4738 #endif // JS_SIMULATOR_ARM64
4739