neon.isa revision 13978:896f9f7a1d16
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-2011, 2015, 2019 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40output header {{
41    template <template <typename T> class Base>
42    StaticInstPtr
43    decodeNeonUThreeUReg(unsigned size,
44                         ExtMachInst machInst, IntRegIndex dest,
45                         IntRegIndex op1, IntRegIndex op2)
46    {
47        switch (size) {
48          case 0:
49            return new Base<uint8_t>(machInst, dest, op1, op2);
50          case 1:
51            return new Base<uint16_t>(machInst, dest, op1, op2);
52          case 2:
53            return new Base<uint32_t>(machInst, dest, op1, op2);
54          case 3:
55            return new Base<uint64_t>(machInst, dest, op1, op2);
56          default:
57            return new Unknown(machInst);
58        }
59    }
60
61    template <template <typename T> class Base>
62    StaticInstPtr
63    decodeNeonSThreeUReg(unsigned size,
64                         ExtMachInst machInst, IntRegIndex dest,
65                         IntRegIndex op1, IntRegIndex op2)
66    {
67        switch (size) {
68          case 0:
69            return new Base<int8_t>(machInst, dest, op1, op2);
70          case 1:
71            return new Base<int16_t>(machInst, dest, op1, op2);
72          case 2:
73            return new Base<int32_t>(machInst, dest, op1, op2);
74          case 3:
75            return new Base<int64_t>(machInst, dest, op1, op2);
76          default:
77            return new Unknown(machInst);
78        }
79    }
80
81    template <template <typename T> class Base>
82    StaticInstPtr
83    decodeNeonUSThreeUReg(bool notSigned, unsigned size,
84                          ExtMachInst machInst, IntRegIndex dest,
85                          IntRegIndex op1, IntRegIndex op2)
86    {
87        if (notSigned) {
88            return decodeNeonUThreeUReg<Base>(size, machInst, dest, op1, op2);
89        } else {
90            return decodeNeonSThreeUReg<Base>(size, machInst, dest, op1, op2);
91        }
92    }
93
94    template <template <typename T> class Base>
95    StaticInstPtr
96    decodeNeonUThreeUSReg(unsigned size,
97                          ExtMachInst machInst, IntRegIndex dest,
98                          IntRegIndex op1, IntRegIndex op2)
99    {
100        switch (size) {
101          case 0:
102            return new Base<uint8_t>(machInst, dest, op1, op2);
103          case 1:
104            return new Base<uint16_t>(machInst, dest, op1, op2);
105          case 2:
106            return new Base<uint32_t>(machInst, dest, op1, op2);
107          default:
108            return new Unknown(machInst);
109        }
110    }
111
112    template <template <typename T> class Base>
113    StaticInstPtr
114    decodeNeonSThreeUSReg(unsigned size,
115                          ExtMachInst machInst, IntRegIndex dest,
116                          IntRegIndex op1, IntRegIndex op2)
117    {
118        switch (size) {
119          case 0:
120            return new Base<int8_t>(machInst, dest, op1, op2);
121          case 1:
122            return new Base<int16_t>(machInst, dest, op1, op2);
123          case 2:
124            return new Base<int32_t>(machInst, dest, op1, op2);
125          default:
126            return new Unknown(machInst);
127        }
128    }
129
130    template <template <typename T> class Base>
131    StaticInstPtr
132    decodeNeonSThreeHAndWReg(unsigned size, ExtMachInst machInst,
133                             IntRegIndex dest, IntRegIndex op1,
134                             IntRegIndex op2)
135    {
136        switch (size) {
137          case 1:
138            return new Base<int16_t>(machInst, dest, op1, op2);
139          case 2:
140            return new Base<int32_t>(machInst, dest, op1, op2);
141          default:
142            return new Unknown(machInst);
143        }
144    }
145
146    template <template <typename T> class Base>
147    StaticInstPtr
148    decodeNeonSThreeImmHAndWReg(unsigned size, ExtMachInst machInst,
149                                IntRegIndex dest, IntRegIndex op1,
150                                IntRegIndex op2, uint64_t imm)
151    {
152        switch (size) {
153          case 1:
154            return new Base<int16_t>(machInst, dest, op1, op2, imm);
155          case 2:
156            return new Base<int32_t>(machInst, dest, op1, op2, imm);
157          default:
158            return new Unknown(machInst);
159        }
160    }
161
162    template <template <typename T> class Base>
163    StaticInstPtr
164    decodeNeonUSThreeUSReg(bool notSigned, unsigned size,
165                           ExtMachInst machInst, IntRegIndex dest,
166                           IntRegIndex op1, IntRegIndex op2)
167    {
168        if (notSigned) {
169            return decodeNeonUThreeUSReg<Base>(
170                    size, machInst, dest, op1, op2);
171        } else {
172            return decodeNeonSThreeUSReg<Base>(
173                    size, machInst, dest, op1, op2);
174        }
175    }
176
177    template <template <typename T> class BaseD,
178              template <typename T> class BaseQ>
179    StaticInstPtr
180    decodeNeonUThreeSReg(bool q, unsigned size,
181                         ExtMachInst machInst, IntRegIndex dest,
182                         IntRegIndex op1, IntRegIndex op2)
183    {
184        if (q) {
185            return decodeNeonUThreeUSReg<BaseQ>(
186                    size, machInst, dest, op1, op2);
187        } else {
188            return decodeNeonUThreeUSReg<BaseD>(
189                    size, machInst, dest, op1, op2);
190        }
191    }
192
193    template <template <typename T> class BaseD,
194              template <typename T> class BaseQ>
195    StaticInstPtr
196    decodeNeonSThreeSReg(bool q, unsigned size,
197                         ExtMachInst machInst, IntRegIndex dest,
198                         IntRegIndex op1, IntRegIndex op2)
199    {
200        if (q) {
201            return decodeNeonSThreeUSReg<BaseQ>(
202                    size, machInst, dest, op1, op2);
203        } else {
204            return decodeNeonSThreeUSReg<BaseD>(
205                    size, machInst, dest, op1, op2);
206        }
207    }
208
209    template <template <typename T> class BaseD,
210              template <typename T> class BaseQ>
211    StaticInstPtr
212    decodeNeonSThreeXReg(bool q, unsigned size,
213                         ExtMachInst machInst, IntRegIndex dest,
214                         IntRegIndex op1, IntRegIndex op2)
215    {
216        if (q) {
217            return decodeNeonSThreeUReg<BaseQ>(
218                    size, machInst, dest, op1, op2);
219        } else {
220            return decodeNeonSThreeUSReg<BaseD>(
221                    size, machInst, dest, op1, op2);
222        }
223    }
224
225    template <template <typename T> class BaseD,
226              template <typename T> class BaseQ>
227    StaticInstPtr
228    decodeNeonUThreeXReg(bool q, unsigned size,
229                         ExtMachInst machInst, IntRegIndex dest,
230                         IntRegIndex op1, IntRegIndex op2)
231    {
232        if (q) {
233            return decodeNeonUThreeUReg<BaseQ>(
234                    size, machInst, dest, op1, op2);
235        } else {
236            return decodeNeonUThreeUSReg<BaseD>(
237                    size, machInst, dest, op1, op2);
238        }
239    }
240
241    template <template <typename T> class BaseD,
242              template <typename T> class BaseQ>
243    StaticInstPtr
244    decodeNeonUSThreeSReg(bool q, bool notSigned, unsigned size,
245                          ExtMachInst machInst, IntRegIndex dest,
246                          IntRegIndex op1, IntRegIndex op2)
247    {
248        if (notSigned) {
249            return decodeNeonUThreeSReg<BaseD, BaseQ>(
250                    q, size, machInst, dest, op1, op2);
251        } else {
252            return decodeNeonSThreeSReg<BaseD, BaseQ>(
253                    q, size, machInst, dest, op1, op2);
254        }
255    }
256
257    template <template <typename T> class BaseD,
258              template <typename T> class BaseQ>
259    StaticInstPtr
260    decodeNeonUThreeReg(bool q, unsigned size,
261                        ExtMachInst machInst, IntRegIndex dest,
262                        IntRegIndex op1, IntRegIndex op2)
263    {
264        if (q) {
265            return decodeNeonUThreeUReg<BaseQ>(
266                    size, machInst, dest, op1, op2);
267        } else {
268            return decodeNeonUThreeUReg<BaseD>(
269                    size, machInst, dest, op1, op2);
270        }
271    }
272
273    template <template <typename T> class BaseD,
274              template <typename T> class BaseQ>
275    StaticInstPtr
276    decodeNeonSThreeReg(bool q, unsigned size,
277                        ExtMachInst machInst, IntRegIndex dest,
278                        IntRegIndex op1, IntRegIndex op2)
279    {
280        if (q) {
281            return decodeNeonSThreeUReg<BaseQ>(
282                    size, machInst, dest, op1, op2);
283        } else {
284            return decodeNeonSThreeUReg<BaseD>(
285                    size, machInst, dest, op1, op2);
286        }
287    }
288
289    template <template <typename T> class BaseD,
290              template <typename T> class BaseQ>
291    StaticInstPtr
292    decodeNeonUSThreeReg(bool q, bool notSigned, unsigned size,
293                         ExtMachInst machInst, IntRegIndex dest,
294                         IntRegIndex op1, IntRegIndex op2)
295    {
296        if (notSigned) {
297            return decodeNeonUThreeReg<BaseD, BaseQ>(
298                    q, size, machInst, dest, op1, op2);
299        } else {
300            return decodeNeonSThreeReg<BaseD, BaseQ>(
301                    q, size, machInst, dest, op1, op2);
302        }
303    }
304
305    template <template <typename T> class BaseD,
306              template <typename T> class BaseQ>
307    StaticInstPtr
308    decodeNeonUThreeFpReg(bool q, unsigned size, ExtMachInst machInst,
309                          IntRegIndex dest, IntRegIndex op1, IntRegIndex op2)
310    {
311        if (q) {
312            if (size)
313                return new BaseQ<uint64_t>(machInst, dest, op1, op2);
314            else
315                return new BaseQ<uint32_t>(machInst, dest, op1, op2);
316        } else {
317            if (size)
318                return new Unknown(machInst);
319            else
320                return new BaseD<uint32_t>(machInst, dest, op1, op2);
321        }
322    }
323
324    template <template <typename T> class Base>
325    StaticInstPtr
326    decodeNeonUThreeScFpReg(bool size, ExtMachInst machInst,
327                            IntRegIndex dest, IntRegIndex op1, IntRegIndex op2)
328    {
329        if (size)
330            return new Base<uint64_t>(machInst, dest, op1, op2);
331        else
332            return new Base<uint32_t>(machInst, dest, op1, op2);
333    }
334
335    template <template <typename T> class Base>
336    StaticInstPtr
337    decodeNeonUThreeImmScFpReg(bool size, ExtMachInst machInst,
338                               IntRegIndex dest, IntRegIndex op1,
339                               IntRegIndex op2, uint64_t imm)
340    {
341        if (size)
342            return new Base<uint64_t>(machInst, dest, op1, op2, imm);
343        else
344            return new Base<uint32_t>(machInst, dest, op1, op2, imm);
345    }
346
347    template <template <typename T> class BaseD,
348              template <typename T> class BaseQ>
349    StaticInstPtr
350    decodeNeonUThreeImmHAndWReg(bool q, unsigned size, ExtMachInst machInst,
351                                IntRegIndex dest, IntRegIndex op1,
352                                IntRegIndex op2, uint64_t imm)
353    {
354        if (q) {
355            switch (size) {
356              case 1:
357                return new BaseQ<uint16_t>(machInst, dest, op1, op2, imm);
358              case 2:
359                return new BaseQ<uint32_t>(machInst, dest, op1, op2, imm);
360              default:
361                return new Unknown(machInst);
362            }
363        } else {
364            switch (size) {
365              case 1:
366                return new BaseD<uint16_t>(machInst, dest, op1, op2, imm);
367              case 2:
368                return new BaseD<uint32_t>(machInst, dest, op1, op2, imm);
369              default:
370                return new Unknown(machInst);
371            }
372        }
373    }
374
375    template <template <typename T> class BaseD,
376              template <typename T> class BaseQ>
377    StaticInstPtr
378    decodeNeonSThreeImmHAndWReg(bool q, unsigned size, ExtMachInst machInst,
379                                IntRegIndex dest, IntRegIndex op1,
380                                IntRegIndex op2, uint64_t imm)
381    {
382        if (q) {
383            switch (size) {
384              case 1:
385                return new BaseQ<int16_t>(machInst, dest, op1, op2, imm);
386              case 2:
387                return new BaseQ<int32_t>(machInst, dest, op1, op2, imm);
388              default:
389                return new Unknown(machInst);
390            }
391        } else {
392            switch (size) {
393              case 1:
394                return new BaseD<int16_t>(machInst, dest, op1, op2, imm);
395              case 2:
396                return new BaseD<int32_t>(machInst, dest, op1, op2, imm);
397              default:
398                return new Unknown(machInst);
399            }
400        }
401    }
402
403    template <template <typename T> class BaseD,
404              template <typename T> class BaseQ>
405    StaticInstPtr
406    decodeNeonUThreeImmFpReg(bool q, unsigned size, ExtMachInst machInst,
407                             IntRegIndex dest, IntRegIndex op1,
408                             IntRegIndex op2, uint64_t imm)
409    {
410        if (q) {
411            if (size)
412                return new BaseQ<uint64_t>(machInst, dest, op1, op2, imm);
413            else
414                return new BaseQ<uint32_t>(machInst, dest, op1, op2, imm);
415        } else {
416            if (size)
417                return new Unknown(machInst);
418            else
419                return new BaseD<uint32_t>(machInst, dest, op1, op2, imm);
420        }
421    }
422
423    template <template <typename T> class BaseD,
424              template <typename T> class BaseQ>
425    StaticInstPtr
426    decodeNeonUTwoShiftReg(bool q, unsigned size,
427                           ExtMachInst machInst, IntRegIndex dest,
428                           IntRegIndex op1, uint64_t imm)
429    {
430        if (q) {
431            switch (size) {
432              case 0:
433                return new BaseQ<uint8_t>(machInst, dest, op1, imm);
434              case 1:
435                return new BaseQ<uint16_t>(machInst, dest, op1, imm);
436              case 2:
437                return new BaseQ<uint32_t>(machInst, dest, op1, imm);
438              case 3:
439                return new BaseQ<uint64_t>(machInst, dest, op1, imm);
440              default:
441                return new Unknown(machInst);
442            }
443        } else {
444            switch (size) {
445              case 0:
446                return new BaseD<uint8_t>(machInst, dest, op1, imm);
447              case 1:
448                return new BaseD<uint16_t>(machInst, dest, op1, imm);
449              case 2:
450                return new BaseD<uint32_t>(machInst, dest, op1, imm);
451              case 3:
452                return new BaseD<uint64_t>(machInst, dest, op1, imm);
453              default:
454                return new Unknown(machInst);
455            }
456        }
457    }
458
459    template <template <typename T> class BaseD,
460              template <typename T> class BaseQ>
461    StaticInstPtr
462    decodeNeonSTwoShiftReg(bool q, unsigned size,
463                           ExtMachInst machInst, IntRegIndex dest,
464                           IntRegIndex op1, uint64_t imm)
465    {
466        if (q) {
467            switch (size) {
468              case 0:
469                return new BaseQ<int8_t>(machInst, dest, op1, imm);
470              case 1:
471                return new BaseQ<int16_t>(machInst, dest, op1, imm);
472              case 2:
473                return new BaseQ<int32_t>(machInst, dest, op1, imm);
474              case 3:
475                return new BaseQ<int64_t>(machInst, dest, op1, imm);
476              default:
477                return new Unknown(machInst);
478            }
479        } else {
480            switch (size) {
481              case 0:
482                return new BaseD<int8_t>(machInst, dest, op1, imm);
483              case 1:
484                return new BaseD<int16_t>(machInst, dest, op1, imm);
485              case 2:
486                return new BaseD<int32_t>(machInst, dest, op1, imm);
487              case 3:
488                return new BaseD<int64_t>(machInst, dest, op1, imm);
489              default:
490                return new Unknown(machInst);
491            }
492        }
493    }
494
495
496    template <template <typename T> class BaseD,
497              template <typename T> class BaseQ>
498    StaticInstPtr
499    decodeNeonUSTwoShiftReg(bool q, bool notSigned, unsigned size,
500                            ExtMachInst machInst, IntRegIndex dest,
501                            IntRegIndex op1, uint64_t imm)
502    {
503        if (notSigned) {
504            return decodeNeonUTwoShiftReg<BaseD, BaseQ>(
505                    q, size, machInst, dest, op1, imm);
506        } else {
507            return decodeNeonSTwoShiftReg<BaseD, BaseQ>(
508                    q, size, machInst, dest, op1, imm);
509        }
510    }
511
512    template <template <typename T> class Base>
513    StaticInstPtr
514    decodeNeonUTwoShiftUSReg(unsigned size,
515                             ExtMachInst machInst, IntRegIndex dest,
516                             IntRegIndex op1, uint64_t imm)
517    {
518        switch (size) {
519          case 0:
520            return new Base<uint8_t>(machInst, dest, op1, imm);
521          case 1:
522            return new Base<uint16_t>(machInst, dest, op1, imm);
523          case 2:
524            return new Base<uint32_t>(machInst, dest, op1, imm);
525          default:
526            return new Unknown(machInst);
527        }
528    }
529
530    template <template <typename T> class Base>
531    StaticInstPtr
532    decodeNeonUTwoShiftUReg(unsigned size,
533                            ExtMachInst machInst, IntRegIndex dest,
534                            IntRegIndex op1, uint64_t imm)
535    {
536        switch (size) {
537          case 0:
538            return new Base<uint8_t>(machInst, dest, op1, imm);
539          case 1:
540            return new Base<uint16_t>(machInst, dest, op1, imm);
541          case 2:
542            return new Base<uint32_t>(machInst, dest, op1, imm);
543          case 3:
544            return new Base<uint64_t>(machInst, dest, op1, imm);
545          default:
546            return new Unknown(machInst);
547        }
548    }
549
550    template <template <typename T> class Base>
551    StaticInstPtr
552    decodeNeonSTwoShiftUReg(unsigned size,
553                            ExtMachInst machInst, IntRegIndex dest,
554                            IntRegIndex op1, uint64_t imm)
555    {
556        switch (size) {
557          case 0:
558            return new Base<int8_t>(machInst, dest, op1, imm);
559          case 1:
560            return new Base<int16_t>(machInst, dest, op1, imm);
561          case 2:
562            return new Base<int32_t>(machInst, dest, op1, imm);
563          case 3:
564            return new Base<int64_t>(machInst, dest, op1, imm);
565          default:
566            return new Unknown(machInst);
567        }
568    }
569
570    template <template <typename T> class BaseD,
571              template <typename T> class BaseQ>
572    StaticInstPtr
573    decodeNeonUTwoShiftSReg(bool q, unsigned size,
574                            ExtMachInst machInst, IntRegIndex dest,
575                            IntRegIndex op1, uint64_t imm)
576    {
577        if (q) {
578            return decodeNeonUTwoShiftUSReg<BaseQ>(
579                    size, machInst, dest, op1, imm);
580        } else {
581            return decodeNeonUTwoShiftUSReg<BaseD>(
582                    size, machInst, dest, op1, imm);
583        }
584    }
585
586    template <template <typename T> class Base>
587    StaticInstPtr
588    decodeNeonSTwoShiftUSReg(unsigned size,
589                             ExtMachInst machInst, IntRegIndex dest,
590                             IntRegIndex op1, uint64_t imm)
591    {
592        switch (size) {
593          case 0:
594            return new Base<int8_t>(machInst, dest, op1, imm);
595          case 1:
596            return new Base<int16_t>(machInst, dest, op1, imm);
597          case 2:
598            return new Base<int32_t>(machInst, dest, op1, imm);
599          default:
600            return new Unknown(machInst);
601        }
602    }
603
604    template <template <typename T> class BaseD,
605              template <typename T> class BaseQ>
606    StaticInstPtr
607    decodeNeonSTwoShiftSReg(bool q, unsigned size,
608                            ExtMachInst machInst, IntRegIndex dest,
609                            IntRegIndex op1, uint64_t imm)
610    {
611        if (q) {
612            return decodeNeonSTwoShiftUSReg<BaseQ>(
613                    size, machInst, dest, op1, imm);
614        } else {
615            return decodeNeonSTwoShiftUSReg<BaseD>(
616                    size, machInst, dest, op1, imm);
617        }
618    }
619
620    template <template <typename T> class BaseD,
621              template <typename T> class BaseQ>
622    StaticInstPtr
623    decodeNeonUSTwoShiftSReg(bool q, bool notSigned, unsigned size,
624                             ExtMachInst machInst, IntRegIndex dest,
625                             IntRegIndex op1, uint64_t imm)
626    {
627        if (notSigned) {
628            return decodeNeonUTwoShiftSReg<BaseD, BaseQ>(
629                    q, size, machInst, dest, op1, imm);
630        } else {
631            return decodeNeonSTwoShiftSReg<BaseD, BaseQ>(
632                    q, size, machInst, dest, op1, imm);
633        }
634    }
635
636    template <template <typename T> class BaseD,
637              template <typename T> class BaseQ>
638    StaticInstPtr
639    decodeNeonUTwoShiftXReg(bool q, unsigned size, ExtMachInst machInst,
640                            IntRegIndex dest, IntRegIndex op1, uint64_t imm)
641    {
642        if (q) {
643            return decodeNeonUTwoShiftUReg<BaseQ>(
644                size, machInst, dest, op1, imm);
645        } else {
646            return decodeNeonUTwoShiftUSReg<BaseD>(
647                size, machInst, dest, op1, imm);
648        }
649    }
650
651    template <template <typename T> class BaseD,
652              template <typename T> class BaseQ>
653    StaticInstPtr
654    decodeNeonSTwoShiftXReg(bool q, unsigned size, ExtMachInst machInst,
655                            IntRegIndex dest, IntRegIndex op1, uint64_t imm)
656    {
657        if (q) {
658            return decodeNeonSTwoShiftUReg<BaseQ>(
659                size, machInst, dest, op1, imm);
660        } else {
661            return decodeNeonSTwoShiftUSReg<BaseD>(
662                size, machInst, dest, op1, imm);
663        }
664    }
665
666    template <template <typename T> class Base>
667    StaticInstPtr
668    decodeNeonUTwoShiftUFpReg(unsigned size, ExtMachInst machInst,
669                              IntRegIndex dest, IntRegIndex op1, uint64_t imm)
670    {
671        if (size)
672            return new Base<uint64_t>(machInst, dest, op1, imm);
673        else
674            return new Base<uint32_t>(machInst, dest, op1, imm);
675    }
676
677    template <template <typename T> class BaseD,
678              template <typename T> class BaseQ>
679    StaticInstPtr
680    decodeNeonUTwoShiftFpReg(bool q, unsigned size, ExtMachInst machInst,
681                             IntRegIndex dest, IntRegIndex op1, uint64_t imm)
682    {
683        if (q) {
684            if (size)
685                return new BaseQ<uint64_t>(machInst, dest, op1, imm);
686            else
687                return new BaseQ<uint32_t>(machInst, dest, op1, imm);
688        } else {
689            if (size)
690                return new Unknown(machInst);
691            else
692                return new BaseD<uint32_t>(machInst, dest, op1, imm);
693        }
694    }
695
696    template <template <typename T> class Base>
697    StaticInstPtr
698    decodeNeonUTwoMiscUSReg(unsigned size,
699                            ExtMachInst machInst, IntRegIndex dest,
700                            IntRegIndex op1)
701    {
702        switch (size) {
703          case 0:
704            return new Base<uint8_t>(machInst, dest, op1);
705          case 1:
706            return new Base<uint16_t>(machInst, dest, op1);
707          case 2:
708            return new Base<uint32_t>(machInst, dest, op1);
709          default:
710            return new Unknown(machInst);
711        }
712    }
713
714    template <template <typename T> class Base>
715    StaticInstPtr
716    decodeNeonSTwoMiscUSReg(unsigned size,
717                            ExtMachInst machInst, IntRegIndex dest,
718                            IntRegIndex op1)
719    {
720        switch (size) {
721          case 0:
722            return new Base<int8_t>(machInst, dest, op1);
723          case 1:
724            return new Base<int16_t>(machInst, dest, op1);
725          case 2:
726            return new Base<int32_t>(machInst, dest, op1);
727          default:
728            return new Unknown(machInst);
729        }
730    }
731
732    template <template <typename T> class BaseD,
733              template <typename T> class BaseQ>
734    StaticInstPtr
735    decodeNeonUTwoMiscSReg(bool q, unsigned size,
736                           ExtMachInst machInst, IntRegIndex dest,
737                           IntRegIndex op1)
738    {
739        if (q) {
740            return decodeNeonUTwoMiscUSReg<BaseQ>(size, machInst, dest, op1);
741        } else {
742            return decodeNeonUTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
743        }
744    }
745
746    template <template <typename T> class BaseD,
747              template <typename T> class BaseQ>
748    StaticInstPtr
749    decodeNeonSTwoMiscSReg(bool q, unsigned size,
750                           ExtMachInst machInst, IntRegIndex dest,
751                           IntRegIndex op1)
752    {
753        if (q) {
754            return decodeNeonSTwoMiscUSReg<BaseQ>(size, machInst, dest, op1);
755        } else {
756            return decodeNeonSTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
757        }
758    }
759
760    template <template <typename T> class Base>
761    StaticInstPtr
762    decodeNeonUTwoMiscUReg(unsigned size,
763                           ExtMachInst machInst, IntRegIndex dest,
764                           IntRegIndex op1)
765    {
766        switch (size) {
767          case 0:
768            return new Base<uint8_t>(machInst, dest, op1);
769          case 1:
770            return new Base<uint16_t>(machInst, dest, op1);
771          case 2:
772            return new Base<uint32_t>(machInst, dest, op1);
773          case 3:
774            return new Base<uint64_t>(machInst, dest, op1);
775          default:
776            return new Unknown(machInst);
777        }
778    }
779
780    template <template <typename T> class Base>
781    StaticInstPtr
782    decodeNeonSTwoMiscUReg(unsigned size,
783                           ExtMachInst machInst, IntRegIndex dest,
784                           IntRegIndex op1)
785    {
786        switch (size) {
787          case 0:
788            return new Base<int8_t>(machInst, dest, op1);
789          case 1:
790            return new Base<int16_t>(machInst, dest, op1);
791          case 2:
792            return new Base<int32_t>(machInst, dest, op1);
793          case 3:
794            return new Base<int64_t>(machInst, dest, op1);
795          default:
796            return new Unknown(machInst);
797        }
798    }
799
800    template <template <typename T> class BaseD,
801              template <typename T> class BaseQ>
802    StaticInstPtr
803    decodeNeonSTwoMiscReg(bool q, unsigned size,
804                          ExtMachInst machInst, IntRegIndex dest,
805                          IntRegIndex op1)
806    {
807        if (q) {
808            return decodeNeonSTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
809        } else {
810            return decodeNeonSTwoMiscUReg<BaseD>(size, machInst, dest, op1);
811        }
812    }
813
814    template <template <typename T> class BaseD,
815              template <typename T> class BaseQ>
816    StaticInstPtr
817    decodeNeonUTwoMiscReg(bool q, unsigned size,
818                          ExtMachInst machInst, IntRegIndex dest,
819                          IntRegIndex op1)
820    {
821        if (q) {
822            return decodeNeonUTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
823        } else {
824            return decodeNeonUTwoMiscUReg<BaseD>(size, machInst, dest, op1);
825        }
826    }
827
828    template <template <typename T> class BaseD,
829              template <typename T> class BaseQ>
830    StaticInstPtr
831    decodeNeonUSTwoMiscSReg(bool q, bool notSigned, unsigned size,
832                            ExtMachInst machInst, IntRegIndex dest,
833                            IntRegIndex op1)
834    {
835        if (notSigned) {
836            return decodeNeonUTwoShiftSReg<BaseD, BaseQ>(
837                    q, size, machInst, dest, op1);
838        } else {
839            return decodeNeonSTwoShiftSReg<BaseD, BaseQ>(
840                    q, size, machInst, dest, op1);
841        }
842    }
843
844    template <template <typename T> class BaseD,
845              template <typename T> class BaseQ>
846    StaticInstPtr
847    decodeNeonUTwoMiscXReg(bool q, unsigned size, ExtMachInst machInst,
848                           IntRegIndex dest, IntRegIndex op1)
849    {
850        if (q) {
851            return decodeNeonUTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
852        } else {
853            return decodeNeonUTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
854        }
855    }
856
857    template <template <typename T> class BaseD,
858              template <typename T> class BaseQ>
859    StaticInstPtr
860    decodeNeonSTwoMiscXReg(bool q, unsigned size, ExtMachInst machInst,
861                           IntRegIndex dest, IntRegIndex op1)
862    {
863        if (q) {
864            return decodeNeonSTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
865        } else {
866            return decodeNeonSTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
867        }
868    }
869
870    template <template <typename T> class BaseD,
871              template <typename T> class BaseQ>
872    StaticInstPtr
873    decodeNeonUTwoMiscFpReg(bool q, unsigned size, ExtMachInst machInst,
874                            IntRegIndex dest, IntRegIndex op1)
875    {
876        if (q) {
877            if (size)
878                return new BaseQ<uint64_t>(machInst, dest, op1);
879            else
880                return new BaseQ<uint32_t>(machInst, dest, op1);
881        } else {
882            if (size)
883                return new Unknown(machInst);
884            else
885                return new BaseD<uint32_t>(machInst, dest, op1);
886        }
887    }
888
889    template <template <typename T> class BaseD,
890              template <typename T> class BaseQ>
891    StaticInstPtr
892    decodeNeonUTwoMiscPwiseScFpReg(unsigned size, ExtMachInst machInst,
893                                   IntRegIndex dest, IntRegIndex op1)
894    {
895        if (size)
896            return new BaseQ<uint64_t>(machInst, dest, op1);
897        else
898            return new BaseD<uint32_t>(machInst, dest, op1);
899    }
900
901    template <template <typename T> class Base>
902    StaticInstPtr
903    decodeNeonUTwoMiscScFpReg(unsigned size, ExtMachInst machInst,
904                              IntRegIndex dest, IntRegIndex op1)
905    {
906        if (size)
907            return new Base<uint64_t>(machInst, dest, op1);
908        else
909            return new Base<uint32_t>(machInst, dest, op1);
910    }
911
912    template <template <typename T> class BaseD,
913              template <typename T> class BaseQ>
914    StaticInstPtr
915    decodeNeonUAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
916                              IntRegIndex dest, IntRegIndex op1)
917    {
918        if (q) {
919            switch (size) {
920              case 0x0:
921                return new BaseQ<uint8_t>(machInst, dest, op1);
922              case 0x1:
923                return new BaseQ<uint16_t>(machInst, dest, op1);
924              case 0x2:
925                return new BaseQ<uint32_t>(machInst, dest, op1);
926              default:
927                return new Unknown(machInst);
928            }
929        } else {
930            switch (size) {
931              case 0x0:
932                return new BaseD<uint8_t>(machInst, dest, op1);
933              case 0x1:
934                return new BaseD<uint16_t>(machInst, dest, op1);
935              default:
936                return new Unknown(machInst);
937            }
938        }
939    }
940
941    template <template <typename T> class BaseD,
942              template <typename T> class BaseQ,
943              template <typename T> class BaseBQ>
944    StaticInstPtr
945    decodeNeonUAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
946                              IntRegIndex dest, IntRegIndex op1)
947    {
948        if (q) {
949            switch (size) {
950              case 0x0:
951                return new BaseQ<uint8_t>(machInst, dest, op1);
952              case 0x1:
953                return new BaseQ<uint16_t>(machInst, dest, op1);
954              case 0x2:
955                return new BaseBQ<uint32_t>(machInst, dest, op1);
956              default:
957                return new Unknown(machInst);
958            }
959        } else {
960            switch (size) {
961              case 0x0:
962                return new BaseD<uint8_t>(machInst, dest, op1);
963              case 0x1:
964                return new BaseD<uint16_t>(machInst, dest, op1);
965              default:
966                return new Unknown(machInst);
967            }
968        }
969    }
970
971    template <template <typename T> class BaseD,
972              template <typename T> class BaseQ>
973    StaticInstPtr
974    decodeNeonSAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
975                              IntRegIndex dest, IntRegIndex op1)
976    {
977        if (q) {
978            switch (size) {
979              case 0x0:
980                return new BaseQ<int8_t>(machInst, dest, op1);
981              case 0x1:
982                return new BaseQ<int16_t>(machInst, dest, op1);
983              case 0x2:
984                return new BaseQ<int32_t>(machInst, dest, op1);
985              default:
986                return new Unknown(machInst);
987            }
988        } else {
989            switch (size) {
990              case 0x0:
991                return new BaseD<int8_t>(machInst, dest, op1);
992              case 0x1:
993                return new BaseD<int16_t>(machInst, dest, op1);
994              default:
995                return new Unknown(machInst);
996            }
997        }
998    }
999
1000    template <template <typename T> class BaseD,
1001              template <typename T> class BaseQ,
1002              template <typename T> class BaseBQ>
1003    StaticInstPtr
1004    decodeNeonUAcrossLanesLongReg(bool q, unsigned size, ExtMachInst machInst,
1005                                  IntRegIndex dest, IntRegIndex op1)
1006    {
1007        if (q) {
1008            switch (size) {
1009              case 0x0:
1010                return new BaseQ<uint8_t>(machInst, dest, op1);
1011              case 0x1:
1012                return new BaseQ<uint16_t>(machInst, dest, op1);
1013              case 0x2:
1014                return new BaseBQ<uint32_t>(machInst, dest, op1);
1015              default:
1016                return new Unknown(machInst);
1017            }
1018        } else {
1019            switch (size) {
1020              case 0x0:
1021                return new BaseD<uint8_t>(machInst, dest, op1);
1022              case 0x1:
1023                return new BaseD<uint16_t>(machInst, dest, op1);
1024              default:
1025                return new Unknown(machInst);
1026            }
1027        }
1028    }
1029
1030    template <template <typename T> class BaseD,
1031              template <typename T> class BaseQ,
1032              template <typename T> class BaseBQ>
1033    StaticInstPtr
1034    decodeNeonSAcrossLanesLongReg(bool q, unsigned size, ExtMachInst machInst,
1035                                  IntRegIndex dest, IntRegIndex op1)
1036    {
1037        if (q) {
1038            switch (size) {
1039              case 0x0:
1040                return new BaseQ<int8_t>(machInst, dest, op1);
1041              case 0x1:
1042                return new BaseQ<int16_t>(machInst, dest, op1);
1043              case 0x2:
1044                return new BaseBQ<int32_t>(machInst, dest, op1);
1045              default:
1046                return new Unknown(machInst);
1047            }
1048        } else {
1049            switch (size) {
1050              case 0x0:
1051                return new BaseD<int8_t>(machInst, dest, op1);
1052              case 0x1:
1053                return new BaseD<int16_t>(machInst, dest, op1);
1054              default:
1055                return new Unknown(machInst);
1056            }
1057        }
1058    }
1059}};
1060
1061let {{
1062    header_output = ""
1063    exec_output = ""
1064
1065    vcompares = '''
1066    static float
1067    vcgtFunc(float op1, float op2)
1068    {
1069        if (std::isnan(op1) || std::isnan(op2))
1070            return 2.0;
1071        return (op1 > op2) ? 0.0 : 1.0;
1072    }
1073
1074    static float
1075    vcgeFunc(float op1, float op2)
1076    {
1077        if (std::isnan(op1) || std::isnan(op2))
1078            return 2.0;
1079        return (op1 >= op2) ? 0.0 : 1.0;
1080    }
1081
1082    static float
1083    vceqFunc(float op1, float op2)
1084    {
1085        if (isSnan(op1) || isSnan(op2))
1086            return 2.0;
1087        return (op1 == op2) ? 0.0 : 1.0;
1088    }
1089'''
1090    vcomparesL = '''
1091    static float
1092    vcleFunc(float op1, float op2)
1093    {
1094        if (std::isnan(op1) || std::isnan(op2))
1095            return 2.0;
1096        return (op1 <= op2) ? 0.0 : 1.0;
1097    }
1098
1099    static float
1100    vcltFunc(float op1, float op2)
1101    {
1102        if (std::isnan(op1) || std::isnan(op2))
1103            return 2.0;
1104        return (op1 < op2) ? 0.0 : 1.0;
1105    }
1106'''
1107    vacomparesG = '''
1108    static float
1109    vacgtFunc(float op1, float op2)
1110    {
1111        if (std::isnan(op1) || std::isnan(op2))
1112            return 2.0;
1113        return (fabsf(op1) > fabsf(op2)) ? 0.0 : 1.0;
1114    }
1115
1116    static float
1117    vacgeFunc(float op1, float op2)
1118    {
1119        if (std::isnan(op1) || std::isnan(op2))
1120            return 2.0;
1121        return (fabsf(op1) >= fabsf(op2)) ? 0.0 : 1.0;
1122    }
1123'''
1124
1125    exec_output += vcompares + vacomparesG
1126
1127    smallUnsignedTypes = ("uint8_t", "uint16_t", "uint32_t")
1128    unsignedTypes = smallUnsignedTypes + ("uint64_t",)
1129    smallSignedTypes = ("int8_t", "int16_t", "int32_t")
1130    signedTypes = smallSignedTypes + ("int64_t",)
1131    smallTypes = smallUnsignedTypes + smallSignedTypes
1132    allTypes = unsignedTypes + signedTypes
1133
1134    def threeEqualRegInst(name, Name, opClass, types, rCount, op,
1135                          readDest=False, pairwise=False,
1136                          standardFpcsr=False):
1137        global header_output, exec_output
1138        eWalkCode = simdEnabledCheckCode + '''
1139        RegVect srcReg1, srcReg2, destReg;
1140        '''
1141        for reg in range(rCount):
1142            eWalkCode += '''
1143                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1144                srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
1145            ''' % { "reg" : reg }
1146            if readDest:
1147                eWalkCode += '''
1148                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1149                ''' % { "reg" : reg }
1150        readDestCode = ''
1151        if standardFpcsr:
1152            eWalkCode += '''
1153            FPSCR fpscr = fpStandardFPSCRValue((FPSCR)FpscrExc);
1154            '''
1155        if readDest:
1156            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1157        if pairwise:
1158            eWalkCode += '''
1159            for (unsigned i = 0; i < eCount; i++) {
1160                Element srcElem1 = gtoh(2 * i < eCount ?
1161                                        srcReg1.elements[2 * i] :
1162                                        srcReg2.elements[2 * i - eCount]);
1163                Element srcElem2 = gtoh(2 * i < eCount ?
1164                                        srcReg1.elements[2 * i + 1] :
1165                                        srcReg2.elements[2 * i + 1 - eCount]);
1166                Element destElem;
1167                %(readDest)s
1168                %(op)s
1169                destReg.elements[i] = htog(destElem);
1170            }
1171            ''' % { "op" : op, "readDest" : readDestCode }
1172        else:
1173            eWalkCode += '''
1174            for (unsigned i = 0; i < eCount; i++) {
1175                Element srcElem1 = gtoh(srcReg1.elements[i]);
1176                Element srcElem2 = gtoh(srcReg2.elements[i]);
1177                Element destElem;
1178                %(readDest)s
1179                %(op)s
1180                destReg.elements[i] = htog(destElem);
1181            }
1182            ''' % { "op" : op, "readDest" : readDestCode }
1183        if standardFpcsr:
1184            eWalkCode += '''
1185            FpscrExc = fpscr;
1186            '''
1187        for reg in range(rCount):
1188            eWalkCode += '''
1189            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1190            ''' % { "reg" : reg }
1191        iop = InstObjParams(name, Name,
1192                            "RegRegRegOp",
1193                            { "code": eWalkCode,
1194                              "r_count": rCount,
1195                              "predicate_test": predicateTest,
1196                              "op_class": opClass }, [])
1197        header_output += NeonRegRegRegOpDeclare.subst(iop)
1198        exec_output += NeonEqualRegExecute.subst(iop)
1199        for type in types:
1200            substDict = { "targs" : type,
1201                          "class_name" : Name }
1202            exec_output += NeonExecDeclare.subst(substDict)
1203
1204    def threeEqualRegInstFp(name, Name, opClass, types, rCount, op,
1205                            readDest=False, pairwise=False, toInt=False):
1206        global header_output, exec_output
1207        eWalkCode = simdEnabledCheckCode + '''
1208        typedef float FloatVect[rCount];
1209        FloatVect srcRegs1, srcRegs2;
1210        '''
1211        if toInt:
1212            eWalkCode += 'RegVect destRegs;\n'
1213        else:
1214            eWalkCode += 'FloatVect destRegs;\n'
1215        for reg in range(rCount):
1216            eWalkCode += '''
1217                srcRegs1[%(reg)d] = FpOp1P%(reg)d;
1218                srcRegs2[%(reg)d] = FpOp2P%(reg)d;
1219            ''' % { "reg" : reg }
1220            if readDest:
1221                if toInt:
1222                    eWalkCode += '''
1223                        destRegs.regs[%(reg)d] = FpDestP%(reg)d.bits;
1224                    ''' % { "reg" : reg }
1225                else:
1226                    eWalkCode += '''
1227                        destRegs[%(reg)d] = FpDestP%(reg)d;
1228                    ''' % { "reg" : reg }
1229        readDestCode = ''
1230        if readDest:
1231            readDestCode = 'destReg = destRegs[r];'
1232        destType = 'float'
1233        writeDest = 'destRegs[r] = destReg;'
1234        if toInt:
1235            destType = 'uint32_t'
1236            writeDest = 'destRegs.regs[r] = destReg;'
1237        if pairwise:
1238            eWalkCode += '''
1239            for (unsigned r = 0; r < rCount; r++) {
1240                float srcReg1 = (2 * r < rCount) ?
1241                    srcRegs1[2 * r] : srcRegs2[2 * r - rCount];
1242                float srcReg2 = (2 * r < rCount) ?
1243                    srcRegs1[2 * r + 1] : srcRegs2[2 * r + 1 - rCount];
1244                %(destType)s destReg;
1245                %(readDest)s
1246                %(op)s
1247                %(writeDest)s
1248            }
1249            ''' % { "op" : op,
1250                    "readDest" : readDestCode,
1251                    "destType" : destType,
1252                    "writeDest" : writeDest }
1253        else:
1254            eWalkCode += '''
1255            for (unsigned r = 0; r < rCount; r++) {
1256                float srcReg1 = srcRegs1[r];
1257                float srcReg2 = srcRegs2[r];
1258                %(destType)s destReg;
1259                %(readDest)s
1260                %(op)s
1261                %(writeDest)s
1262            }
1263            ''' % { "op" : op,
1264                    "readDest" : readDestCode,
1265                    "destType" : destType,
1266                    "writeDest" : writeDest }
1267        for reg in range(rCount):
1268            if toInt:
1269                eWalkCode += '''
1270                FpDestP%(reg)d_uw = destRegs.regs[%(reg)d];
1271                ''' % { "reg" : reg }
1272            else:
1273                eWalkCode += '''
1274                FpDestP%(reg)d = destRegs[%(reg)d];
1275                ''' % { "reg" : reg }
1276        iop = InstObjParams(name, Name,
1277                            "FpRegRegRegOp",
1278                            { "code": eWalkCode,
1279                              "r_count": rCount,
1280                              "predicate_test": predicateTest,
1281                              "op_class": opClass }, [])
1282        header_output += NeonRegRegRegOpDeclare.subst(iop)
1283        exec_output += NeonEqualRegExecute.subst(iop)
1284        for type in types:
1285            substDict = { "targs" : type,
1286                          "class_name" : Name }
1287            exec_output += NeonExecDeclare.subst(substDict)
1288
1289    def threeUnequalRegInst(name, Name, opClass, types, op,
1290                            bigSrc1, bigSrc2, bigDest, readDest):
1291        global header_output, exec_output
1292        src1Cnt = src2Cnt = destCnt = 2
1293        src1Prefix = src2Prefix = destPrefix = ''
1294        if bigSrc1:
1295            src1Cnt = 4
1296            src1Prefix = 'Big'
1297        if bigSrc2:
1298            src2Cnt = 4
1299            src2Prefix = 'Big'
1300        if bigDest:
1301            destCnt = 4
1302            destPrefix = 'Big'
1303        eWalkCode = simdEnabledCheckCode + '''
1304            %sRegVect srcReg1;
1305            %sRegVect srcReg2;
1306            %sRegVect destReg;
1307        ''' % (src1Prefix, src2Prefix, destPrefix)
1308        for reg in range(src1Cnt):
1309            eWalkCode += '''
1310                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1311            ''' % { "reg" : reg }
1312        for reg in range(src2Cnt):
1313            eWalkCode += '''
1314                srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
1315            ''' % { "reg" : reg }
1316        if readDest:
1317            for reg in range(destCnt):
1318                eWalkCode += '''
1319                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1320                ''' % { "reg" : reg }
1321        readDestCode = ''
1322        if readDest:
1323            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1324        eWalkCode += '''
1325        for (unsigned i = 0; i < eCount; i++) {
1326            %(src1Prefix)sElement srcElem1 = gtoh(srcReg1.elements[i]);
1327            %(src1Prefix)sElement srcElem2 = gtoh(srcReg2.elements[i]);
1328            %(destPrefix)sElement destElem;
1329            %(readDest)s
1330            %(op)s
1331            destReg.elements[i] = htog(destElem);
1332        }
1333        ''' % { "op" : op, "readDest" : readDestCode,
1334                "src1Prefix" : src1Prefix, "src2Prefix" : src2Prefix,
1335                "destPrefix" : destPrefix }
1336        for reg in range(destCnt):
1337            eWalkCode += '''
1338            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1339            ''' % { "reg" : reg }
1340        iop = InstObjParams(name, Name,
1341                            "RegRegRegOp",
1342                            { "code": eWalkCode,
1343                              "r_count": 2,
1344                              "predicate_test": predicateTest,
1345                              "op_class": opClass }, [])
1346        header_output += NeonRegRegRegOpDeclare.subst(iop)
1347        exec_output += NeonUnequalRegExecute.subst(iop)
1348        for type in types:
1349            substDict = { "targs" : type,
1350                          "class_name" : Name }
1351            exec_output += NeonExecDeclare.subst(substDict)
1352
1353    def threeRegNarrowInst(name, Name, opClass, types, op, readDest=False):
1354        threeUnequalRegInst(name, Name, opClass, types, op,
1355                            True, True, False, readDest)
1356
1357    def threeRegLongInst(name, Name, opClass, types, op, readDest=False):
1358        threeUnequalRegInst(name, Name, opClass, types, op,
1359                            False, False, True, readDest)
1360
1361    def threeRegWideInst(name, Name, opClass, types, op, readDest=False):
1362        threeUnequalRegInst(name, Name, opClass, types, op,
1363                            True, False, True, readDest)
1364
1365    def twoEqualRegInst(name, Name, opClass, types, rCount, op, readDest=False):
1366        global header_output, exec_output
1367        eWalkCode = simdEnabledCheckCode + '''
1368        RegVect srcReg1, srcReg2, destReg;
1369        '''
1370        for reg in range(rCount):
1371            eWalkCode += '''
1372                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1373                srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
1374            ''' % { "reg" : reg }
1375            if readDest:
1376                eWalkCode += '''
1377                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1378                ''' % { "reg" : reg }
1379        readDestCode = ''
1380        if readDest:
1381            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1382        eWalkCode += '''
1383        if (imm < 0 && imm >= eCount) {
1384            fault = std::make_shared<UndefinedInstruction>(machInst, false,
1385                                                           mnemonic);
1386        } else {
1387            for (unsigned i = 0; i < eCount; i++) {
1388                Element srcElem1 = gtoh(srcReg1.elements[i]);
1389                Element srcElem2 = gtoh(srcReg2.elements[imm]);
1390                Element destElem;
1391                %(readDest)s
1392                %(op)s
1393                destReg.elements[i] = htog(destElem);
1394            }
1395        }
1396        ''' % { "op" : op, "readDest" : readDestCode }
1397        for reg in range(rCount):
1398            eWalkCode += '''
1399            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1400            ''' % { "reg" : reg }
1401        iop = InstObjParams(name, Name,
1402                            "RegRegRegImmOp",
1403                            { "code": eWalkCode,
1404                              "r_count": rCount,
1405                              "predicate_test": predicateTest,
1406                              "op_class": opClass }, [])
1407        header_output += NeonRegRegRegImmOpDeclare.subst(iop)
1408        exec_output += NeonEqualRegExecute.subst(iop)
1409        for type in types:
1410            substDict = { "targs" : type,
1411                          "class_name" : Name }
1412            exec_output += NeonExecDeclare.subst(substDict)
1413
1414    def twoRegLongInst(name, Name, opClass, types, op, readDest=False):
1415        global header_output, exec_output
1416        rCount = 2
1417        eWalkCode = simdEnabledCheckCode + '''
1418        RegVect srcReg1, srcReg2;
1419        BigRegVect destReg;
1420        '''
1421        for reg in range(rCount):
1422            eWalkCode += '''
1423                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1424                srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);;
1425            ''' % { "reg" : reg }
1426        if readDest:
1427            for reg in range(2 * rCount):
1428                eWalkCode += '''
1429                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1430                ''' % { "reg" : reg }
1431        readDestCode = ''
1432        if readDest:
1433            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1434        eWalkCode += '''
1435        if (imm < 0 && imm >= eCount) {
1436            fault = std::make_shared<UndefinedInstruction>(machInst, false,
1437                                                          mnemonic);
1438        } else {
1439            for (unsigned i = 0; i < eCount; i++) {
1440                Element srcElem1 = gtoh(srcReg1.elements[i]);
1441                Element srcElem2 = gtoh(srcReg2.elements[imm]);
1442                BigElement destElem;
1443                %(readDest)s
1444                %(op)s
1445                destReg.elements[i] = htog(destElem);
1446            }
1447        }
1448        ''' % { "op" : op, "readDest" : readDestCode }
1449        for reg in range(2 * rCount):
1450            eWalkCode += '''
1451            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1452            ''' % { "reg" : reg }
1453        iop = InstObjParams(name, Name,
1454                            "RegRegRegImmOp",
1455                            { "code": eWalkCode,
1456                              "r_count": rCount,
1457                              "predicate_test": predicateTest,
1458                              "op_class": opClass }, [])
1459        header_output += NeonRegRegRegImmOpDeclare.subst(iop)
1460        exec_output += NeonUnequalRegExecute.subst(iop)
1461        for type in types:
1462            substDict = { "targs" : type,
1463                          "class_name" : Name }
1464            exec_output += NeonExecDeclare.subst(substDict)
1465
1466    def twoEqualRegInstFp(name, Name, opClass, types, rCount, op, readDest=False):
1467        global header_output, exec_output
1468        eWalkCode = simdEnabledCheckCode + '''
1469        typedef float FloatVect[rCount];
1470        FloatVect srcRegs1, srcRegs2, destRegs;
1471        '''
1472        for reg in range(rCount):
1473            eWalkCode += '''
1474                srcRegs1[%(reg)d] = FpOp1P%(reg)d;
1475                srcRegs2[%(reg)d] = FpOp2P%(reg)d;
1476            ''' % { "reg" : reg }
1477            if readDest:
1478                eWalkCode += '''
1479                    destRegs[%(reg)d] = FpDestP%(reg)d;
1480                ''' % { "reg" : reg }
1481        readDestCode = ''
1482        if readDest:
1483            readDestCode = 'destReg = destRegs[i];'
1484        eWalkCode += '''
1485        if (imm < 0 && imm >= eCount) {
1486            fault = std::make_shared<UndefinedInstruction>(machInst, false,
1487                                                           mnemonic);
1488        } else {
1489            for (unsigned i = 0; i < rCount; i++) {
1490                float srcReg1 = srcRegs1[i];
1491                float srcReg2 = srcRegs2[imm];
1492                float destReg;
1493                %(readDest)s
1494                %(op)s
1495                destRegs[i] = destReg;
1496            }
1497        }
1498        ''' % { "op" : op, "readDest" : readDestCode }
1499        for reg in range(rCount):
1500            eWalkCode += '''
1501            FpDestP%(reg)d = destRegs[%(reg)d];
1502            ''' % { "reg" : reg }
1503        iop = InstObjParams(name, Name,
1504                            "FpRegRegRegImmOp",
1505                            { "code": eWalkCode,
1506                              "r_count": rCount,
1507                              "predicate_test": predicateTest,
1508                              "op_class": opClass }, [])
1509        header_output += NeonRegRegRegImmOpDeclare.subst(iop)
1510        exec_output += NeonEqualRegExecute.subst(iop)
1511        for type in types:
1512            substDict = { "targs" : type,
1513                          "class_name" : Name }
1514            exec_output += NeonExecDeclare.subst(substDict)
1515
1516    def twoRegShiftInst(name, Name, opClass, types, rCount, op,
1517            readDest=False, toInt=False, fromInt=False):
1518        global header_output, exec_output
1519        eWalkCode = simdEnabledCheckCode + '''
1520        RegVect srcRegs1, destRegs;
1521        '''
1522        for reg in range(rCount):
1523            eWalkCode += '''
1524                srcRegs1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1525            ''' % { "reg" : reg }
1526            if readDest:
1527                eWalkCode += '''
1528                    destRegs.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1529                ''' % { "reg" : reg }
1530        readDestCode = ''
1531        if readDest:
1532            readDestCode = 'destElem = gtoh(destRegs.elements[i]);'
1533            if toInt:
1534                readDestCode = 'destReg = gtoh(destRegs.regs[i]);'
1535        readOpCode = 'Element srcElem1 = gtoh(srcRegs1.elements[i]);'
1536        if fromInt:
1537            readOpCode = 'uint32_t srcReg1 = gtoh(srcRegs1.regs[i]);'
1538        declDest = 'Element destElem;'
1539        writeDestCode = 'destRegs.elements[i] = htog(destElem);'
1540        if toInt:
1541            declDest = 'uint32_t destReg;'
1542            writeDestCode = 'destRegs.regs[i] = htog(destReg);'
1543        eWalkCode += '''
1544        for (unsigned i = 0; i < eCount; i++) {
1545            %(readOp)s
1546            %(declDest)s
1547            %(readDest)s
1548            %(op)s
1549            %(writeDest)s
1550        }
1551        ''' % { "readOp" : readOpCode,
1552                "declDest" : declDest,
1553                "readDest" : readDestCode,
1554                "op" : op,
1555                "writeDest" : writeDestCode }
1556        for reg in range(rCount):
1557            eWalkCode += '''
1558            FpDestP%(reg)d_uw = gtoh(destRegs.regs[%(reg)d]);
1559            ''' % { "reg" : reg }
1560        iop = InstObjParams(name, Name,
1561                            "RegRegImmOp",
1562                            { "code": eWalkCode,
1563                              "r_count": rCount,
1564                              "predicate_test": predicateTest,
1565                              "op_class": opClass }, [])
1566        header_output += NeonRegRegImmOpDeclare.subst(iop)
1567        exec_output += NeonEqualRegExecute.subst(iop)
1568        for type in types:
1569            substDict = { "targs" : type,
1570                          "class_name" : Name }
1571            exec_output += NeonExecDeclare.subst(substDict)
1572
1573    def twoRegNarrowShiftInst(name, Name, opClass, types, op, readDest=False):
1574        global header_output, exec_output
1575        eWalkCode = simdEnabledCheckCode + '''
1576        BigRegVect srcReg1;
1577        RegVect destReg;
1578        '''
1579        for reg in range(4):
1580            eWalkCode += '''
1581                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1582            ''' % { "reg" : reg }
1583        if readDest:
1584            for reg in range(2):
1585                eWalkCode += '''
1586                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1587                ''' % { "reg" : reg }
1588        readDestCode = ''
1589        if readDest:
1590            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1591        eWalkCode += '''
1592        for (unsigned i = 0; i < eCount; i++) {
1593            BigElement srcElem1 = gtoh(srcReg1.elements[i]);
1594            Element destElem;
1595            %(readDest)s
1596            %(op)s
1597            destReg.elements[i] = htog(destElem);
1598        }
1599        ''' % { "op" : op, "readDest" : readDestCode }
1600        for reg in range(2):
1601            eWalkCode += '''
1602            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1603            ''' % { "reg" : reg }
1604        iop = InstObjParams(name, Name,
1605                            "RegRegImmOp",
1606                            { "code": eWalkCode,
1607                              "r_count": 2,
1608                              "predicate_test": predicateTest,
1609                              "op_class": opClass }, [])
1610        header_output += NeonRegRegImmOpDeclare.subst(iop)
1611        exec_output += NeonUnequalRegExecute.subst(iop)
1612        for type in types:
1613            substDict = { "targs" : type,
1614                          "class_name" : Name }
1615            exec_output += NeonExecDeclare.subst(substDict)
1616
1617    def twoRegLongShiftInst(name, Name, opClass, types, op, readDest=False):
1618        global header_output, exec_output
1619        eWalkCode = simdEnabledCheckCode + '''
1620        RegVect srcReg1;
1621        BigRegVect destReg;
1622        '''
1623        for reg in range(2):
1624            eWalkCode += '''
1625                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1626            ''' % { "reg" : reg }
1627        if readDest:
1628            for reg in range(4):
1629                eWalkCode += '''
1630                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1631                ''' % { "reg" : reg }
1632        readDestCode = ''
1633        if readDest:
1634            readDestCode = 'destReg = gtoh(destReg.elements[i]);'
1635        eWalkCode += '''
1636        for (unsigned i = 0; i < eCount; i++) {
1637            Element srcElem1 = gtoh(srcReg1.elements[i]);
1638            BigElement destElem;
1639            %(readDest)s
1640            %(op)s
1641            destReg.elements[i] = htog(destElem);
1642        }
1643        ''' % { "op" : op, "readDest" : readDestCode }
1644        for reg in range(4):
1645            eWalkCode += '''
1646            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1647            ''' % { "reg" : reg }
1648        iop = InstObjParams(name, Name,
1649                            "RegRegImmOp",
1650                            { "code": eWalkCode,
1651                              "r_count": 2,
1652                              "predicate_test": predicateTest,
1653                              "op_class": opClass }, [])
1654        header_output += NeonRegRegImmOpDeclare.subst(iop)
1655        exec_output += NeonUnequalRegExecute.subst(iop)
1656        for type in types:
1657            substDict = { "targs" : type,
1658                          "class_name" : Name }
1659            exec_output += NeonExecDeclare.subst(substDict)
1660
1661    def twoRegMiscInst(name, Name, opClass, types, rCount, op, readDest=False):
1662        global header_output, exec_output
1663        eWalkCode = simdEnabledCheckCode + '''
1664        RegVect srcReg1, destReg;
1665        '''
1666        for reg in range(rCount):
1667            eWalkCode += '''
1668                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1669            ''' % { "reg" : reg }
1670            if readDest:
1671                eWalkCode += '''
1672                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1673                ''' % { "reg" : reg }
1674        readDestCode = ''
1675        if readDest:
1676            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1677        eWalkCode += '''
1678        for (unsigned i = 0; i < eCount; i++) {
1679            unsigned j = i;
1680            Element srcElem1 = gtoh(srcReg1.elements[i]);
1681            Element destElem;
1682            %(readDest)s
1683            %(op)s
1684            destReg.elements[j] = htog(destElem);
1685        }
1686        ''' % { "op" : op, "readDest" : readDestCode }
1687        for reg in range(rCount):
1688            eWalkCode += '''
1689            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1690            ''' % { "reg" : reg }
1691        iop = InstObjParams(name, Name,
1692                            "RegRegOp",
1693                            { "code": eWalkCode,
1694                              "r_count": rCount,
1695                              "predicate_test": predicateTest,
1696                              "op_class": opClass }, [])
1697        header_output += NeonRegRegOpDeclare.subst(iop)
1698        exec_output += NeonEqualRegExecute.subst(iop)
1699        for type in types:
1700            substDict = { "targs" : type,
1701                          "class_name" : Name }
1702            exec_output += NeonExecDeclare.subst(substDict)
1703
1704    def twoRegMiscScInst(name, Name, opClass, types, rCount, op, readDest=False):
1705        global header_output, exec_output
1706        eWalkCode = simdEnabledCheckCode + '''
1707        RegVect srcReg1, destReg;
1708        '''
1709        for reg in range(rCount):
1710            eWalkCode += '''
1711                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1712            ''' % { "reg" : reg }
1713            if readDest:
1714                eWalkCode += '''
1715                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1716                ''' % { "reg" : reg }
1717        readDestCode = ''
1718        if readDest:
1719            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1720        eWalkCode += '''
1721        for (unsigned i = 0; i < eCount; i++) {
1722            Element srcElem1 = gtoh(srcReg1.elements[imm]);
1723            Element destElem;
1724            %(readDest)s
1725            %(op)s
1726            destReg.elements[i] = htog(destElem);
1727        }
1728        ''' % { "op" : op, "readDest" : readDestCode }
1729        for reg in range(rCount):
1730            eWalkCode += '''
1731            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1732            ''' % { "reg" : reg }
1733        iop = InstObjParams(name, Name,
1734                            "RegRegImmOp",
1735                            { "code": eWalkCode,
1736                              "r_count": rCount,
1737                              "predicate_test": predicateTest,
1738                              "op_class": opClass }, [])
1739        header_output += NeonRegRegImmOpDeclare.subst(iop)
1740        exec_output += NeonEqualRegExecute.subst(iop)
1741        for type in types:
1742            substDict = { "targs" : type,
1743                          "class_name" : Name }
1744            exec_output += NeonExecDeclare.subst(substDict)
1745
1746    def twoRegMiscScramble(name, Name, opClass, types, rCount, op, readDest=False):
1747        global header_output, exec_output
1748        eWalkCode = simdEnabledCheckCode + '''
1749        RegVect srcReg1, destReg;
1750        '''
1751        for reg in range(rCount):
1752            eWalkCode += '''
1753                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1754                destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1755            ''' % { "reg" : reg }
1756            if readDest:
1757                eWalkCode += '''
1758                ''' % { "reg" : reg }
1759        readDestCode = ''
1760        if readDest:
1761            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1762        eWalkCode += op
1763        for reg in range(rCount):
1764            eWalkCode += '''
1765            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1766            FpOp1P%(reg)d_uw = gtoh(srcReg1.regs[%(reg)d]);
1767            ''' % { "reg" : reg }
1768        iop = InstObjParams(name, Name,
1769                            "RegRegOp",
1770                            { "code": eWalkCode,
1771                              "r_count": rCount,
1772                              "predicate_test": predicateTest,
1773                              "op_class": opClass }, [])
1774        header_output += NeonRegRegOpDeclare.subst(iop)
1775        exec_output += NeonEqualRegExecute.subst(iop)
1776        for type in types:
1777            substDict = { "targs" : type,
1778                          "class_name" : Name }
1779            exec_output += NeonExecDeclare.subst(substDict)
1780
1781    def twoRegMiscInstFp(name, Name, opClass, types, rCount, op,
1782            readDest=False, toInt=False):
1783        global header_output, exec_output
1784        eWalkCode = simdEnabledCheckCode + '''
1785        typedef float FloatVect[rCount];
1786        FloatVect srcRegs1;
1787        '''
1788        if toInt:
1789            eWalkCode += 'RegVect destRegs;\n'
1790        else:
1791            eWalkCode += 'FloatVect destRegs;\n'
1792        for reg in range(rCount):
1793            eWalkCode += '''
1794                srcRegs1[%(reg)d] = FpOp1P%(reg)d;
1795            ''' % { "reg" : reg }
1796            if readDest:
1797                if toInt:
1798                    eWalkCode += '''
1799                        destRegs.regs[%(reg)d] = FpDestP%(reg)d.bits;
1800                    ''' % { "reg" : reg }
1801                else:
1802                    eWalkCode += '''
1803                        destRegs[%(reg)d] = FpDestP%(reg)d;
1804                    ''' % { "reg" : reg }
1805        readDestCode = ''
1806        if readDest:
1807            readDestCode = 'destReg = destRegs[i];'
1808        destType = 'float'
1809        writeDest = 'destRegs[r] = destReg;'
1810        if toInt:
1811            destType = 'uint32_t'
1812            writeDest = 'destRegs.regs[r] = destReg;'
1813        eWalkCode += '''
1814        for (unsigned r = 0; r < rCount; r++) {
1815            float srcReg1 = srcRegs1[r];
1816            %(destType)s destReg;
1817            %(readDest)s
1818            %(op)s
1819            %(writeDest)s
1820        }
1821        ''' % { "op" : op,
1822                "readDest" : readDestCode,
1823                "destType" : destType,
1824                "writeDest" : writeDest }
1825        for reg in range(rCount):
1826            if toInt:
1827                eWalkCode += '''
1828                FpDestP%(reg)d_uw = destRegs.regs[%(reg)d];
1829                ''' % { "reg" : reg }
1830            else:
1831                eWalkCode += '''
1832                FpDestP%(reg)d = destRegs[%(reg)d];
1833                ''' % { "reg" : reg }
1834        iop = InstObjParams(name, Name,
1835                            "FpRegRegOp",
1836                            { "code": eWalkCode,
1837                              "r_count": rCount,
1838                              "predicate_test": predicateTest,
1839                              "op_class": opClass }, [])
1840        header_output += NeonRegRegOpDeclare.subst(iop)
1841        exec_output += NeonEqualRegExecute.subst(iop)
1842        for type in types:
1843            substDict = { "targs" : type,
1844                          "class_name" : Name }
1845            exec_output += NeonExecDeclare.subst(substDict)
1846
1847    def twoRegCondenseInst(name, Name, opClass, types, rCount, op, readDest=False):
1848        global header_output, exec_output
1849        eWalkCode = simdEnabledCheckCode + '''
1850        RegVect srcRegs;
1851        BigRegVect destReg;
1852        '''
1853        for reg in range(rCount):
1854            eWalkCode += '''
1855                srcRegs.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1856            ''' % { "reg" : reg }
1857            if readDest:
1858                eWalkCode += '''
1859                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1860                ''' % { "reg" : reg }
1861        readDestCode = ''
1862        if readDest:
1863            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1864        eWalkCode += '''
1865        for (unsigned i = 0; i < eCount / 2; i++) {
1866            Element srcElem1 = gtoh(srcRegs.elements[2 * i]);
1867            Element srcElem2 = gtoh(srcRegs.elements[2 * i + 1]);
1868            BigElement destElem;
1869            %(readDest)s
1870            %(op)s
1871            destReg.elements[i] = htog(destElem);
1872        }
1873        ''' % { "op" : op, "readDest" : readDestCode }
1874        for reg in range(rCount):
1875            eWalkCode += '''
1876            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1877            ''' % { "reg" : reg }
1878        iop = InstObjParams(name, Name,
1879                            "RegRegOp",
1880                            { "code": eWalkCode,
1881                              "r_count": rCount,
1882                              "predicate_test": predicateTest,
1883                              "op_class": opClass }, [])
1884        header_output += NeonRegRegOpDeclare.subst(iop)
1885        exec_output += NeonUnequalRegExecute.subst(iop)
1886        for type in types:
1887            substDict = { "targs" : type,
1888                          "class_name" : Name }
1889            exec_output += NeonExecDeclare.subst(substDict)
1890
1891    def twoRegNarrowMiscInst(name, Name, opClass, types, op, readDest=False):
1892        global header_output, exec_output
1893        eWalkCode = simdEnabledCheckCode + '''
1894        BigRegVect srcReg1;
1895        RegVect destReg;
1896        '''
1897        for reg in range(4):
1898            eWalkCode += '''
1899                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1900            ''' % { "reg" : reg }
1901        if readDest:
1902            for reg in range(2):
1903                eWalkCode += '''
1904                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1905                ''' % { "reg" : reg }
1906        readDestCode = ''
1907        if readDest:
1908            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1909        eWalkCode += '''
1910        for (unsigned i = 0; i < eCount; i++) {
1911            BigElement srcElem1 = gtoh(srcReg1.elements[i]);
1912            Element destElem;
1913            %(readDest)s
1914            %(op)s
1915            destReg.elements[i] = htog(destElem);
1916        }
1917        ''' % { "op" : op, "readDest" : readDestCode }
1918        for reg in range(2):
1919            eWalkCode += '''
1920            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1921            ''' % { "reg" : reg }
1922        iop = InstObjParams(name, Name,
1923                            "RegRegOp",
1924                            { "code": eWalkCode,
1925                              "r_count": 2,
1926                              "predicate_test": predicateTest,
1927                              "op_class": opClass }, [])
1928        header_output += NeonRegRegOpDeclare.subst(iop)
1929        exec_output += NeonUnequalRegExecute.subst(iop)
1930        for type in types:
1931            substDict = { "targs" : type,
1932                          "class_name" : Name }
1933            exec_output += NeonExecDeclare.subst(substDict)
1934
1935    def oneRegImmInst(name, Name, opClass, types, rCount, op, readDest=False):
1936        global header_output, exec_output
1937        eWalkCode = simdEnabledCheckCode + '''
1938        RegVect destReg;
1939        '''
1940        if readDest:
1941            for reg in range(rCount):
1942                eWalkCode += '''
1943                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1944                ''' % { "reg" : reg }
1945        readDestCode = ''
1946        if readDest:
1947            readDestCode = 'destElem = gtoh(destReg.elements[i]);'
1948        eWalkCode += '''
1949        for (unsigned i = 0; i < eCount; i++) {
1950            Element destElem;
1951            %(readDest)s
1952            %(op)s
1953            destReg.elements[i] = htog(destElem);
1954        }
1955        ''' % { "op" : op, "readDest" : readDestCode }
1956        for reg in range(rCount):
1957            eWalkCode += '''
1958            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
1959            ''' % { "reg" : reg }
1960        iop = InstObjParams(name, Name,
1961                            "RegImmOp",
1962                            { "code": eWalkCode,
1963                              "r_count": rCount,
1964                              "predicate_test": predicateTest,
1965                              "op_class": opClass }, [])
1966        header_output += NeonRegImmOpDeclare.subst(iop)
1967        exec_output += NeonEqualRegExecute.subst(iop)
1968        for type in types:
1969            substDict = { "targs" : type,
1970                          "class_name" : Name }
1971            exec_output += NeonExecDeclare.subst(substDict)
1972
1973    def twoRegLongMiscInst(name, Name, opClass, types, op, readDest=False):
1974        global header_output, exec_output
1975        eWalkCode = simdEnabledCheckCode + '''
1976        RegVect srcReg1;
1977        BigRegVect destReg;
1978        '''
1979        for reg in range(2):
1980            eWalkCode += '''
1981                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
1982            ''' % { "reg" : reg }
1983        if readDest:
1984            for reg in range(4):
1985                eWalkCode += '''
1986                    destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
1987                ''' % { "reg" : reg }
1988        readDestCode = ''
1989        if readDest:
1990            readDestCode = 'destReg = gtoh(destReg.elements[i]);'
1991        eWalkCode += '''
1992        for (unsigned i = 0; i < eCount; i++) {
1993            Element srcElem1 = gtoh(srcReg1.elements[i]);
1994            BigElement destElem;
1995            %(readDest)s
1996            %(op)s
1997            destReg.elements[i] = htog(destElem);
1998        }
1999        ''' % { "op" : op, "readDest" : readDestCode }
2000        for reg in range(4):
2001            eWalkCode += '''
2002            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
2003            ''' % { "reg" : reg }
2004        iop = InstObjParams(name, Name,
2005                            "RegRegOp",
2006                            { "code": eWalkCode,
2007                              "r_count": 2,
2008                              "predicate_test": predicateTest,
2009                              "op_class": opClass }, [])
2010        header_output += NeonRegRegOpDeclare.subst(iop)
2011        exec_output += NeonUnequalRegExecute.subst(iop)
2012        for type in types:
2013            substDict = { "targs" : type,
2014                          "class_name" : Name }
2015            exec_output += NeonExecDeclare.subst(substDict)
2016
2017    vhaddCode = '''
2018        Element carryBit =
2019            (((unsigned)srcElem1 & 0x1) +
2020             ((unsigned)srcElem2 & 0x1)) >> 1;
2021        // Use division instead of a shift to ensure the sign extension works
2022        // right. The compiler will figure out if it can be a shift. Mask the
2023        // inputs so they get truncated correctly.
2024        destElem = (((srcElem1 & ~(Element)1) / 2) +
2025                    ((srcElem2 & ~(Element)1) / 2)) + carryBit;
2026    '''
2027    threeEqualRegInst("vhadd", "VhaddD", "SimdAddOp", allTypes, 2, vhaddCode)
2028    threeEqualRegInst("vhadd", "VhaddQ", "SimdAddOp", allTypes, 4, vhaddCode)
2029
2030    vrhaddCode = '''
2031        Element carryBit =
2032            (((unsigned)srcElem1 & 0x1) +
2033             ((unsigned)srcElem2 & 0x1) + 1) >> 1;
2034        // Use division instead of a shift to ensure the sign extension works
2035        // right. The compiler will figure out if it can be a shift. Mask the
2036        // inputs so they get truncated correctly.
2037        destElem = (((srcElem1 & ~(Element)1) / 2) +
2038                    ((srcElem2 & ~(Element)1) / 2)) + carryBit;
2039    '''
2040    threeEqualRegInst("vrhadd", "VrhaddD", "SimdAddOp", allTypes, 2, vrhaddCode)
2041    threeEqualRegInst("vrhadd", "VrhaddQ", "SimdAddOp", allTypes, 4, vrhaddCode)
2042
2043    vhsubCode = '''
2044        Element barrowBit =
2045            (((srcElem1 & 0x1) - (srcElem2 & 0x1)) >> 1) & 0x1;
2046        // Use division instead of a shift to ensure the sign extension works
2047        // right. The compiler will figure out if it can be a shift. Mask the
2048        // inputs so they get truncated correctly.
2049        destElem = (((srcElem1 & ~(Element)1) / 2) -
2050                    ((srcElem2 & ~(Element)1) / 2)) - barrowBit;
2051    '''
2052    threeEqualRegInst("vhsub", "VhsubD", "SimdAddOp", allTypes, 2, vhsubCode)
2053    threeEqualRegInst("vhsub", "VhsubQ", "SimdAddOp", allTypes, 4, vhsubCode)
2054
2055    vandCode = '''
2056        destElem = srcElem1 & srcElem2;
2057    '''
2058    threeEqualRegInst("vand", "VandD", "SimdAluOp", unsignedTypes, 2, vandCode)
2059    threeEqualRegInst("vand", "VandQ", "SimdAluOp", unsignedTypes, 4, vandCode)
2060
2061    vbicCode = '''
2062        destElem = srcElem1 & ~srcElem2;
2063    '''
2064    threeEqualRegInst("vbic", "VbicD", "SimdAluOp", unsignedTypes, 2, vbicCode)
2065    threeEqualRegInst("vbic", "VbicQ", "SimdAluOp", unsignedTypes, 4, vbicCode)
2066
2067    vorrCode = '''
2068        destElem = srcElem1 | srcElem2;
2069    '''
2070    threeEqualRegInst("vorr", "VorrD", "SimdAluOp", unsignedTypes, 2, vorrCode)
2071    threeEqualRegInst("vorr", "VorrQ", "SimdAluOp", unsignedTypes, 4, vorrCode)
2072
2073    threeEqualRegInst("vmov", "VmovD", "SimdMiscOp", unsignedTypes, 2, vorrCode)
2074    threeEqualRegInst("vmov", "VmovQ", "SimdMiscOp", unsignedTypes, 4, vorrCode)
2075
2076    vornCode = '''
2077        destElem = srcElem1 | ~srcElem2;
2078    '''
2079    threeEqualRegInst("vorn", "VornD", "SimdAluOp", unsignedTypes, 2, vornCode)
2080    threeEqualRegInst("vorn", "VornQ", "SimdAluOp", unsignedTypes, 4, vornCode)
2081
2082    veorCode = '''
2083        destElem = srcElem1 ^ srcElem2;
2084    '''
2085    threeEqualRegInst("veor", "VeorD", "SimdAluOp", unsignedTypes, 2, veorCode)
2086    threeEqualRegInst("veor", "VeorQ", "SimdAluOp", unsignedTypes, 4, veorCode)
2087
2088    vbifCode = '''
2089        destElem = (destElem & srcElem2) | (srcElem1 & ~srcElem2);
2090    '''
2091    threeEqualRegInst("vbif", "VbifD", "SimdAluOp", unsignedTypes, 2, vbifCode, True)
2092    threeEqualRegInst("vbif", "VbifQ", "SimdAluOp", unsignedTypes, 4, vbifCode, True)
2093    vbitCode = '''
2094        destElem = (srcElem1 & srcElem2) | (destElem & ~srcElem2);
2095    '''
2096    threeEqualRegInst("vbit", "VbitD", "SimdAluOp", unsignedTypes, 2, vbitCode, True)
2097    threeEqualRegInst("vbit", "VbitQ", "SimdAluOp", unsignedTypes, 4, vbitCode, True)
2098    vbslCode = '''
2099        destElem = (srcElem1 & destElem) | (srcElem2 & ~destElem);
2100    '''
2101    threeEqualRegInst("vbsl", "VbslD", "SimdAluOp", unsignedTypes, 2, vbslCode, True)
2102    threeEqualRegInst("vbsl", "VbslQ", "SimdAluOp", unsignedTypes, 4, vbslCode, True)
2103
2104    vmaxCode = '''
2105        destElem = (srcElem1 > srcElem2) ? srcElem1 : srcElem2;
2106    '''
2107    threeEqualRegInst("vmax", "VmaxD", "SimdCmpOp", allTypes, 2, vmaxCode)
2108    threeEqualRegInst("vmax", "VmaxQ", "SimdCmpOp", allTypes, 4, vmaxCode)
2109
2110    vminCode = '''
2111        destElem = (srcElem1 < srcElem2) ? srcElem1 : srcElem2;
2112    '''
2113    threeEqualRegInst("vmin", "VminD", "SimdCmpOp", allTypes, 2, vminCode)
2114    threeEqualRegInst("vmin", "VminQ", "SimdCmpOp", allTypes, 4, vminCode)
2115
2116    vaddCode = '''
2117        destElem = srcElem1 + srcElem2;
2118    '''
2119    threeEqualRegInst("vadd", "NVaddD", "SimdAddOp", unsignedTypes, 2, vaddCode)
2120    threeEqualRegInst("vadd", "NVaddQ", "SimdAddOp", unsignedTypes, 4, vaddCode)
2121
2122    threeEqualRegInst("vpadd", "NVpaddD", "SimdAddOp", smallUnsignedTypes,
2123                      2, vaddCode, pairwise=True)
2124    vaddlwCode = '''
2125        destElem = (BigElement)srcElem1 + (BigElement)srcElem2;
2126    '''
2127    threeRegLongInst("vaddl", "Vaddl", "SimdAddOp", smallTypes, vaddlwCode)
2128    threeRegWideInst("vaddw", "Vaddw", "SimdAddOp", smallTypes, vaddlwCode)
2129    vaddhnCode = '''
2130        destElem = ((BigElement)srcElem1 + (BigElement)srcElem2) >>
2131                   (sizeof(Element) * 8);
2132    '''
2133    threeRegNarrowInst("vaddhn", "Vaddhn", "SimdAddOp", smallTypes, vaddhnCode)
2134    vraddhnCode = '''
2135        destElem = ((BigElement)srcElem1 + (BigElement)srcElem2 +
2136                    ((BigElement)1 << (sizeof(Element) * 8 - 1))) >>
2137                   (sizeof(Element) * 8);
2138    '''
2139    threeRegNarrowInst("vraddhn", "Vraddhn", "SimdAddOp", smallTypes, vraddhnCode)
2140
2141    vsubCode = '''
2142        destElem = srcElem1 - srcElem2;
2143    '''
2144    threeEqualRegInst("vsub", "NVsubD", "SimdAddOp", unsignedTypes, 2, vsubCode)
2145    threeEqualRegInst("vsub", "NVsubQ", "SimdAddOp", unsignedTypes, 4, vsubCode)
2146    vsublwCode = '''
2147        destElem = (BigElement)srcElem1 - (BigElement)srcElem2;
2148    '''
2149    threeRegLongInst("vsubl", "Vsubl", "SimdAddOp", smallTypes, vsublwCode)
2150    threeRegWideInst("vsubw", "Vsubw", "SimdAddOp", smallTypes, vsublwCode)
2151
2152    vqaddUCode = '''
2153        destElem = srcElem1 + srcElem2;
2154        FPSCR fpscr = (FPSCR) FpscrQc;
2155        if (destElem < srcElem1 || destElem < srcElem2) {
2156            destElem = (Element)(-1);
2157            fpscr.qc = 1;
2158        }
2159        FpscrQc = fpscr;
2160    '''
2161    threeEqualRegInst("vqadd", "VqaddUD", "SimdAddOp", unsignedTypes, 2, vqaddUCode)
2162    threeEqualRegInst("vqadd", "VqaddUQ", "SimdAddOp", unsignedTypes, 4, vqaddUCode)
2163    vsubhnCode = '''
2164        destElem = ((BigElement)srcElem1 - (BigElement)srcElem2) >>
2165                   (sizeof(Element) * 8);
2166    '''
2167    threeRegNarrowInst("vsubhn", "Vsubhn", "SimdAddOp", smallTypes, vsubhnCode)
2168    vrsubhnCode = '''
2169        destElem = ((BigElement)srcElem1 - (BigElement)srcElem2 +
2170                    ((BigElement)1 << (sizeof(Element) * 8 - 1))) >>
2171                   (sizeof(Element) * 8);
2172    '''
2173    threeRegNarrowInst("vrsubhn", "Vrsubhn", "SimdAddOp", smallTypes, vrsubhnCode)
2174
2175    vqaddSCode = '''
2176        destElem = srcElem1 + srcElem2;
2177        FPSCR fpscr = (FPSCR) FpscrQc;
2178        bool negDest = (destElem < 0);
2179        bool negSrc1 = (srcElem1 < 0);
2180        bool negSrc2 = (srcElem2 < 0);
2181        if ((negDest != negSrc1) && (negSrc1 == negSrc2)) {
2182            if (negDest)
2183                /* If (>=0) plus (>=0) yields (<0), saturate to +. */
2184                destElem = std::numeric_limits<Element>::max();
2185            else
2186                /* If (<0) plus (<0) yields (>=0), saturate to -. */
2187                destElem = std::numeric_limits<Element>::min();
2188            fpscr.qc = 1;
2189        }
2190        FpscrQc = fpscr;
2191    '''
2192    threeEqualRegInst("vqadd", "VqaddSD", "SimdAddOp", signedTypes, 2, vqaddSCode)
2193    threeEqualRegInst("vqadd", "VqaddSQ", "SimdAddOp", signedTypes, 4, vqaddSCode)
2194
2195    vqsubUCode = '''
2196        destElem = srcElem1 - srcElem2;
2197        FPSCR fpscr = (FPSCR) FpscrQc;
2198        if (destElem > srcElem1) {
2199            destElem = 0;
2200            fpscr.qc = 1;
2201        }
2202        FpscrQc = fpscr;
2203    '''
2204    threeEqualRegInst("vqsub", "VqsubUD", "SimdAddOp", unsignedTypes, 2, vqsubUCode)
2205    threeEqualRegInst("vqsub", "VqsubUQ", "SimdAddOp", unsignedTypes, 4, vqsubUCode)
2206
2207    vqsubSCode = '''
2208        destElem = srcElem1 - srcElem2;
2209        FPSCR fpscr = (FPSCR) FpscrQc;
2210        bool negDest = (destElem < 0);
2211        bool negSrc1 = (srcElem1 < 0);
2212        bool posSrc2 = (srcElem2 >= 0);
2213        if ((negDest != negSrc1) && (negSrc1 == posSrc2)) {
2214            if (negDest)
2215                /* If (>=0) minus (<0) yields (<0), saturate to +. */
2216                destElem = std::numeric_limits<Element>::max();
2217            else
2218                /* If (<0) minus (>=0) yields (>=0), saturate to -. */
2219                destElem = std::numeric_limits<Element>::min();
2220            fpscr.qc = 1;
2221        }
2222        FpscrQc = fpscr;
2223    '''
2224    threeEqualRegInst("vqsub", "VqsubSD", "SimdAddOp", signedTypes, 2, vqsubSCode)
2225    threeEqualRegInst("vqsub", "VqsubSQ", "SimdAddOp", signedTypes, 4, vqsubSCode)
2226
2227    vcgtCode = '''
2228        destElem =  (srcElem1 > srcElem2) ? (Element)(-1) : 0;
2229    '''
2230    threeEqualRegInst("vcgt", "VcgtD", "SimdCmpOp", allTypes, 2, vcgtCode)
2231    threeEqualRegInst("vcgt", "VcgtQ", "SimdCmpOp", allTypes, 4, vcgtCode)
2232
2233    vcgeCode = '''
2234        destElem =  (srcElem1 >= srcElem2) ? (Element)(-1) : 0;
2235    '''
2236    threeEqualRegInst("vcge", "VcgeD", "SimdCmpOp", allTypes, 2, vcgeCode)
2237    threeEqualRegInst("vcge", "VcgeQ", "SimdCmpOp", allTypes, 4, vcgeCode)
2238
2239    vceqCode = '''
2240        destElem =  (srcElem1 == srcElem2) ? (Element)(-1) : 0;
2241    '''
2242    threeEqualRegInst("vceq", "VceqD", "SimdCmpOp", unsignedTypes, 2, vceqCode)
2243    threeEqualRegInst("vceq", "VceqQ", "SimdCmpOp", unsignedTypes, 4, vceqCode)
2244
2245    vshlCode = '''
2246        int16_t shiftAmt = (int8_t)srcElem2;
2247        if (shiftAmt < 0) {
2248            shiftAmt = -shiftAmt;
2249            if (shiftAmt >= sizeof(Element) * 8) {
2250                shiftAmt = sizeof(Element) * 8 - 1;
2251                destElem = 0;
2252            } else {
2253                destElem = (srcElem1 >> shiftAmt);
2254            }
2255            // Make sure the right shift sign extended when it should.
2256            if (ltz(srcElem1) && !ltz(destElem)) {
2257                destElem |= -((Element)1 << (sizeof(Element) * 8 -
2258                                             1 - shiftAmt));
2259            }
2260        } else {
2261            if (shiftAmt >= sizeof(Element) * 8) {
2262                destElem = 0;
2263            } else {
2264                destElem = srcElem1 << shiftAmt;
2265            }
2266        }
2267    '''
2268    threeEqualRegInst("vshl", "VshlD", "SimdShiftOp", allTypes, 2, vshlCode)
2269    threeEqualRegInst("vshl", "VshlQ", "SimdShiftOp", allTypes, 4, vshlCode)
2270
2271    vrshlCode = '''
2272        int16_t shiftAmt = (int8_t)srcElem2;
2273        if (shiftAmt < 0) {
2274            shiftAmt = -shiftAmt;
2275            Element rBit = 0;
2276            if (shiftAmt <= sizeof(Element) * 8)
2277                rBit = bits(srcElem1, shiftAmt - 1);
2278            if (shiftAmt > sizeof(Element) * 8 && ltz(srcElem1))
2279                rBit = 1;
2280            if (shiftAmt >= sizeof(Element) * 8) {
2281                shiftAmt = sizeof(Element) * 8 - 1;
2282                destElem = 0;
2283            } else {
2284                destElem = (srcElem1 >> shiftAmt);
2285            }
2286            // Make sure the right shift sign extended when it should.
2287            if (ltz(srcElem1) && !ltz(destElem)) {
2288                destElem |= -((Element)1 << (sizeof(Element) * 8 -
2289                                             1 - shiftAmt));
2290            }
2291            destElem += rBit;
2292        } else if (shiftAmt > 0) {
2293            if (shiftAmt >= sizeof(Element) * 8) {
2294                destElem = 0;
2295            } else {
2296                destElem = srcElem1 << shiftAmt;
2297            }
2298        } else {
2299            destElem = srcElem1;
2300        }
2301    '''
2302    threeEqualRegInst("vrshl", "VrshlD", "SimdAluOp", allTypes, 2, vrshlCode)
2303    threeEqualRegInst("vrshl", "VrshlQ", "SimdAluOp", allTypes, 4, vrshlCode)
2304
2305    vqshlUCode = '''
2306        int16_t shiftAmt = (int8_t)srcElem2;
2307        FPSCR fpscr = (FPSCR) FpscrQc;
2308        if (shiftAmt < 0) {
2309            shiftAmt = -shiftAmt;
2310            if (shiftAmt >= sizeof(Element) * 8) {
2311                shiftAmt = sizeof(Element) * 8 - 1;
2312                destElem = 0;
2313            } else {
2314                destElem = (srcElem1 >> shiftAmt);
2315            }
2316        } else if (shiftAmt > 0) {
2317            if (shiftAmt >= sizeof(Element) * 8) {
2318                if (srcElem1 != 0) {
2319                    destElem = mask(sizeof(Element) * 8);
2320                    fpscr.qc = 1;
2321                } else {
2322                    destElem = 0;
2323                }
2324            } else {
2325                if (bits(srcElem1, sizeof(Element) * 8 - 1,
2326                            sizeof(Element) * 8 - shiftAmt)) {
2327                    destElem = mask(sizeof(Element) * 8);
2328                    fpscr.qc = 1;
2329                } else {
2330                    destElem = srcElem1 << shiftAmt;
2331                }
2332            }
2333        } else {
2334            destElem = srcElem1;
2335        }
2336        FpscrQc = fpscr;
2337    '''
2338    threeEqualRegInst("vqshl", "VqshlUD", "SimdAluOp", unsignedTypes, 2, vqshlUCode)
2339    threeEqualRegInst("vqshl", "VqshlUQ", "SimdAluOp", unsignedTypes, 4, vqshlUCode)
2340
2341    vqshlSCode = '''
2342        int16_t shiftAmt = (int8_t)srcElem2;
2343        FPSCR fpscr = (FPSCR) FpscrQc;
2344        if (shiftAmt < 0) {
2345            shiftAmt = -shiftAmt;
2346            if (shiftAmt >= sizeof(Element) * 8) {
2347                shiftAmt = sizeof(Element) * 8 - 1;
2348                destElem = 0;
2349            } else {
2350                destElem = (srcElem1 >> shiftAmt);
2351            }
2352            // Make sure the right shift sign extended when it should.
2353            if (srcElem1 < 0 && destElem >= 0) {
2354                destElem |= -((Element)1 << (sizeof(Element) * 8 -
2355                                             1 - shiftAmt));
2356            }
2357        } else if (shiftAmt > 0) {
2358            bool sat = false;
2359            if (shiftAmt >= sizeof(Element) * 8) {
2360                if (srcElem1 != 0)
2361                    sat = true;
2362                else
2363                    destElem = 0;
2364            } else {
2365                if (bits(srcElem1, sizeof(Element) * 8 - 1,
2366                            sizeof(Element) * 8 - 1 - shiftAmt) !=
2367                        ((srcElem1 < 0) ? mask(shiftAmt + 1) : 0)) {
2368                    sat = true;
2369                } else {
2370                    destElem = srcElem1 << shiftAmt;
2371                }
2372            }
2373            if (sat) {
2374                fpscr.qc = 1;
2375                destElem = mask(sizeof(Element) * 8 - 1);
2376                if (srcElem1 < 0)
2377                    destElem = ~destElem;
2378            }
2379        } else {
2380            destElem = srcElem1;
2381        }
2382        FpscrQc = fpscr;
2383    '''
2384    threeEqualRegInst("vqshl", "VqshlSD", "SimdCmpOp", signedTypes, 2, vqshlSCode)
2385    threeEqualRegInst("vqshl", "VqshlSQ", "SimdCmpOp", signedTypes, 4, vqshlSCode)
2386
2387    vqrshlUCode = '''
2388        int16_t shiftAmt = (int8_t)srcElem2;
2389        FPSCR fpscr = (FPSCR) FpscrQc;
2390        if (shiftAmt < 0) {
2391            shiftAmt = -shiftAmt;
2392            Element rBit = 0;
2393            if (shiftAmt <= sizeof(Element) * 8)
2394                rBit = bits(srcElem1, shiftAmt - 1);
2395            if (shiftAmt >= sizeof(Element) * 8) {
2396                shiftAmt = sizeof(Element) * 8 - 1;
2397                destElem = 0;
2398            } else {
2399                destElem = (srcElem1 >> shiftAmt);
2400            }
2401            destElem += rBit;
2402        } else {
2403            if (shiftAmt >= sizeof(Element) * 8) {
2404                if (srcElem1 != 0) {
2405                    destElem = mask(sizeof(Element) * 8);
2406                    fpscr.qc = 1;
2407                } else {
2408                    destElem = 0;
2409                }
2410            } else {
2411                if (bits(srcElem1, sizeof(Element) * 8 - 1,
2412                            sizeof(Element) * 8 - shiftAmt)) {
2413                    destElem = mask(sizeof(Element) * 8);
2414                    fpscr.qc = 1;
2415                } else {
2416                    destElem = srcElem1 << shiftAmt;
2417                }
2418            }
2419        }
2420        FpscrQc = fpscr;
2421    '''
2422    threeEqualRegInst("vqrshl", "VqrshlUD", "SimdCmpOp", unsignedTypes, 2, vqrshlUCode)
2423    threeEqualRegInst("vqrshl", "VqrshlUQ", "SimdCmpOp", unsignedTypes, 4, vqrshlUCode)
2424
2425    vqrshlSCode = '''
2426        int16_t shiftAmt = (int8_t)srcElem2;
2427        FPSCR fpscr = (FPSCR) FpscrQc;
2428        if (shiftAmt < 0) {
2429            shiftAmt = -shiftAmt;
2430            Element rBit = 0;
2431            if (shiftAmt <= sizeof(Element) * 8)
2432                rBit = bits(srcElem1, shiftAmt - 1);
2433            if (shiftAmt > sizeof(Element) * 8 && srcElem1 < 0)
2434                rBit = 1;
2435            if (shiftAmt >= sizeof(Element) * 8) {
2436                shiftAmt = sizeof(Element) * 8 - 1;
2437                destElem = 0;
2438            } else {
2439                destElem = (srcElem1 >> shiftAmt);
2440            }
2441            // Make sure the right shift sign extended when it should.
2442            if (srcElem1 < 0 && destElem >= 0) {
2443                destElem |= -((Element)1 << (sizeof(Element) * 8 -
2444                                             1 - shiftAmt));
2445            }
2446            destElem += rBit;
2447        } else if (shiftAmt > 0) {
2448            bool sat = false;
2449            if (shiftAmt >= sizeof(Element) * 8) {
2450                if (srcElem1 != 0)
2451                    sat = true;
2452                else
2453                    destElem = 0;
2454            } else {
2455                if (bits(srcElem1, sizeof(Element) * 8 - 1,
2456                            sizeof(Element) * 8 - 1 - shiftAmt) !=
2457                        ((srcElem1 < 0) ? mask(shiftAmt + 1) : 0)) {
2458                    sat = true;
2459                } else {
2460                    destElem = srcElem1 << shiftAmt;
2461                }
2462            }
2463            if (sat) {
2464                fpscr.qc = 1;
2465                destElem = mask(sizeof(Element) * 8 - 1);
2466                if (srcElem1 < 0)
2467                    destElem = ~destElem;
2468            }
2469        } else {
2470            destElem = srcElem1;
2471        }
2472        FpscrQc = fpscr;
2473    '''
2474    threeEqualRegInst("vqrshl", "VqrshlSD", "SimdCmpOp", signedTypes, 2, vqrshlSCode)
2475    threeEqualRegInst("vqrshl", "VqrshlSQ", "SimdCmpOp", signedTypes, 4, vqrshlSCode)
2476
2477    vabaCode = '''
2478        destElem += (srcElem1 > srcElem2) ? (srcElem1 - srcElem2) :
2479                                            (srcElem2 - srcElem1);
2480    '''
2481    threeEqualRegInst("vaba", "VabaD", "SimdAddAccOp", allTypes, 2, vabaCode, True)
2482    threeEqualRegInst("vaba", "VabaQ", "SimdAddAccOp", allTypes, 4, vabaCode, True)
2483    vabalCode = '''
2484        destElem += (srcElem1 > srcElem2) ?
2485            ((BigElement)srcElem1 - (BigElement)srcElem2) :
2486            ((BigElement)srcElem2 - (BigElement)srcElem1);
2487    '''
2488    threeRegLongInst("vabal", "Vabal", "SimdAddAccOp", smallTypes, vabalCode, True)
2489
2490    vabdCode = '''
2491        destElem = (srcElem1 > srcElem2) ? (srcElem1 - srcElem2) :
2492                                           (srcElem2 - srcElem1);
2493    '''
2494    threeEqualRegInst("vabd", "VabdD", "SimdAddOp", allTypes, 2, vabdCode)
2495    threeEqualRegInst("vabd", "VabdQ", "SimdAddOp", allTypes, 4, vabdCode)
2496    vabdlCode = '''
2497        destElem = (srcElem1 > srcElem2) ?
2498            ((BigElement)srcElem1 - (BigElement)srcElem2) :
2499            ((BigElement)srcElem2 - (BigElement)srcElem1);
2500    '''
2501    threeRegLongInst("vabdl", "Vabdl", "SimdAddOp", smallTypes, vabdlCode)
2502
2503    vtstCode = '''
2504        destElem = (srcElem1 & srcElem2) ? (Element)(-1) : 0;
2505    '''
2506    threeEqualRegInst("vtst", "VtstD", "SimdAluOp", unsignedTypes, 2, vtstCode)
2507    threeEqualRegInst("vtst", "VtstQ", "SimdAluOp", unsignedTypes, 4, vtstCode)
2508
2509    vmulCode = '''
2510        destElem = srcElem1 * srcElem2;
2511    '''
2512    threeEqualRegInst("vmul", "NVmulD", "SimdMultOp", allTypes, 2, vmulCode)
2513    threeEqualRegInst("vmul", "NVmulQ", "SimdMultOp", allTypes, 4, vmulCode)
2514    vmullCode = '''
2515        destElem = (BigElement)srcElem1 * (BigElement)srcElem2;
2516    '''
2517    threeRegLongInst("vmull", "Vmull", "SimdMultOp", smallTypes, vmullCode)
2518
2519    vmlaCode = '''
2520        destElem = destElem + srcElem1 * srcElem2;
2521    '''
2522    threeEqualRegInst("vmla", "NVmlaD", "SimdMultAccOp", allTypes, 2, vmlaCode, True)
2523    threeEqualRegInst("vmla", "NVmlaQ", "SimdMultAccOp", allTypes, 4, vmlaCode, True)
2524    vmlalCode = '''
2525        destElem = destElem + (BigElement)srcElem1 * (BigElement)srcElem2;
2526    '''
2527    threeRegLongInst("vmlal", "Vmlal", "SimdMultAccOp", smallTypes, vmlalCode, True)
2528
2529    vqdmlalCode = '''
2530        FPSCR fpscr = (FPSCR) FpscrQc;
2531        BigElement midElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
2532        Element maxNeg = std::numeric_limits<Element>::min();
2533        Element halfNeg = maxNeg / 2;
2534        if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
2535            (srcElem1 == halfNeg && srcElem2 == maxNeg) ||
2536            (srcElem1 == maxNeg && srcElem2 == halfNeg)) {
2537            midElem = ~((BigElement)maxNeg << (sizeof(Element) * 8));
2538            fpscr.qc = 1;
2539        }
2540        bool negPreDest = ltz(destElem);
2541        destElem += midElem;
2542        bool negDest = ltz(destElem);
2543        bool negMid = ltz(midElem);
2544        if (negPreDest == negMid && negMid != negDest) {
2545            destElem = mask(sizeof(BigElement) * 8 - 1);
2546            if (negPreDest)
2547                destElem = ~destElem;
2548            fpscr.qc = 1;
2549        }
2550        FpscrQc = fpscr;
2551    '''
2552    threeRegLongInst("vqdmlal", "Vqdmlal", "SimdMultAccOp", smallTypes, vqdmlalCode, True)
2553
2554    vqdmlslCode = '''
2555        FPSCR fpscr = (FPSCR) FpscrQc;
2556        BigElement midElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
2557        Element maxNeg = std::numeric_limits<Element>::min();
2558        Element halfNeg = maxNeg / 2;
2559        if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
2560            (srcElem1 == halfNeg && srcElem2 == maxNeg) ||
2561            (srcElem1 == maxNeg && srcElem2 == halfNeg)) {
2562            midElem = ~((BigElement)maxNeg << (sizeof(Element) * 8));
2563            fpscr.qc = 1;
2564        }
2565        bool negPreDest = ltz(destElem);
2566        destElem -= midElem;
2567        bool negDest = ltz(destElem);
2568        bool posMid = ltz((BigElement)-midElem);
2569        if (negPreDest == posMid && posMid != negDest) {
2570            destElem = mask(sizeof(BigElement) * 8 - 1);
2571            if (negPreDest)
2572                destElem = ~destElem;
2573            fpscr.qc = 1;
2574        }
2575        FpscrQc = fpscr;
2576    '''
2577    threeRegLongInst("vqdmlsl", "Vqdmlsl", "SimdMultAccOp", smallTypes, vqdmlslCode, True)
2578
2579    vqdmullCode = '''
2580        FPSCR fpscr = (FPSCR) FpscrQc;
2581        destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
2582        if (srcElem1 == srcElem2 &&
2583                srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
2584            destElem = ~((BigElement)srcElem1 << (sizeof(Element) * 8));
2585            fpscr.qc = 1;
2586        }
2587        FpscrQc = fpscr;
2588    '''
2589    threeRegLongInst("vqdmull", "Vqdmull", "SimdMultAccOp", smallTypes, vqdmullCode)
2590
2591    vmlsCode = '''
2592        destElem = destElem - srcElem1 * srcElem2;
2593    '''
2594    threeEqualRegInst("vmls", "NVmlsD", "SimdMultAccOp", allTypes, 2, vmlsCode, True)
2595    threeEqualRegInst("vmls", "NVmlsQ", "SimdMultAccOp", allTypes, 4, vmlsCode, True)
2596    vmlslCode = '''
2597        destElem = destElem - (BigElement)srcElem1 * (BigElement)srcElem2;
2598    '''
2599    threeRegLongInst("vmlsl", "Vmlsl", "SimdMultAccOp", smallTypes, vmlslCode, True)
2600
2601    vmulpCode = '''
2602        destElem = 0;
2603        for (unsigned j = 0; j < sizeof(Element) * 8; j++) {
2604            if (bits(srcElem2, j))
2605                destElem ^= srcElem1 << j;
2606        }
2607    '''
2608    threeEqualRegInst("vmul", "NVmulpD", "SimdMultOp", unsignedTypes, 2, vmulpCode)
2609    threeEqualRegInst("vmul", "NVmulpQ", "SimdMultOp", unsignedTypes, 4, vmulpCode)
2610    vmullpCode = '''
2611        destElem = 0;
2612        for (unsigned j = 0; j < sizeof(Element) * 8; j++) {
2613            if (bits(srcElem2, j))
2614                destElem ^= (BigElement)srcElem1 << j;
2615        }
2616    '''
2617    threeRegLongInst("vmull", "Vmullp", "SimdMultOp", smallUnsignedTypes, vmullpCode)
2618
2619    threeEqualRegInst("vpmax", "VpmaxD", "SimdCmpOp", smallTypes, 2, vmaxCode, pairwise=True)
2620
2621    threeEqualRegInst("vpmin", "VpminD", "SimdCmpOp", smallTypes, 2, vminCode, pairwise=True)
2622
2623    vqdmulhCode = '''
2624        FPSCR fpscr = (FPSCR) FpscrQc;
2625        destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2) >>
2626                   (sizeof(Element) * 8);
2627        if (srcElem1 == srcElem2 &&
2628                srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
2629            destElem = ~srcElem1;
2630            fpscr.qc = 1;
2631        }
2632        FpscrQc = fpscr;
2633    '''
2634    threeEqualRegInst("vqdmulh", "VqdmulhD", "SimdMultOp", smallSignedTypes, 2, vqdmulhCode)
2635    threeEqualRegInst("vqdmulh", "VqdmulhQ", "SimdMultOp", smallSignedTypes, 4, vqdmulhCode)
2636
2637    vqrdmulhCode = '''
2638        FPSCR fpscr = (FPSCR) FpscrQc;
2639        destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2 +
2640                    ((int64_t)1 << (sizeof(Element) * 8 - 1))) >>
2641                   (sizeof(Element) * 8);
2642        Element maxNeg = std::numeric_limits<Element>::min();
2643        Element halfNeg = maxNeg / 2;
2644        if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
2645            (srcElem1 == halfNeg && srcElem2 == maxNeg) ||
2646            (srcElem1 == maxNeg && srcElem2 == halfNeg)) {
2647            if (destElem < 0) {
2648                destElem = mask(sizeof(Element) * 8 - 1);
2649            } else {
2650                destElem = std::numeric_limits<Element>::min();
2651            }
2652            fpscr.qc = 1;
2653        }
2654        FpscrQc = fpscr;
2655    '''
2656    threeEqualRegInst("vqrdmulh", "VqrdmulhD",
2657            "SimdMultOp", smallSignedTypes, 2, vqrdmulhCode)
2658    threeEqualRegInst("vqrdmulh", "VqrdmulhQ",
2659            "SimdMultOp", smallSignedTypes, 4, vqrdmulhCode)
2660
2661    vMinMaxFpCode = '''
2662        destElem = fplib%s<Element>(srcElem1, srcElem2, fpscr);
2663    '''
2664    vMinMaxInsts = [
2665        ("vmax",   "VmaxDFp",   2, "Max",    False, ),
2666        ("vmax",   "VmaxQFp",   4, "Max",    False, ),
2667        ("vmaxnm", "VmaxnmDFp", 2, "MaxNum", False, ),
2668        ("vmaxnm", "VmaxnmQFp", 4, "MaxNum", False, ),
2669        ("vpmax",  "VpmaxDFp",  2, "Max",    True,  ),
2670        ("vpmax",  "VpmaxQFp",  4, "Max",    True,  ),
2671        ("vmin",   "VminDFp",   2, "Min",    False, ),
2672        ("vmin",   "VminQFp",   4, "Min",    False, ),
2673        ("vminnm", "VminnmDFp", 2, "MinNum", False, ),
2674        ("vminnm", "VminnmQFp", 4, "MinNum", False, ),
2675        ("vpmin",  "VpminDFp",  2, "Min",    True,  ),
2676        ("vpmin",  "VpminQFp",  4, "Min",    True,  ),
2677    ]
2678    for name, Name, rCount, op, pairwise in vMinMaxInsts:
2679        threeEqualRegInst(
2680            name,
2681            Name,
2682            "SimdFloatCmpOp",
2683            ("uint32_t",),
2684            rCount,
2685            vMinMaxFpCode % op,
2686            pairwise=pairwise,
2687            standardFpcsr=True,
2688        )
2689
2690    vaddfpCode = '''
2691        FPSCR fpscr = (FPSCR) FpscrExc;
2692        destReg = binaryOp(fpscr, srcReg1, srcReg2, fpAddS,
2693                           true, true, VfpRoundNearest);
2694        FpscrExc = fpscr;
2695    '''
2696    threeEqualRegInstFp("vadd", "VaddDFp", "SimdFloatAddOp", ("float",), 2, vaddfpCode)
2697    threeEqualRegInstFp("vadd", "VaddQFp", "SimdFloatAddOp", ("float",), 4, vaddfpCode)
2698
2699    threeEqualRegInstFp("vpadd", "VpaddDFp", "SimdFloatAddOp", ("float",),
2700                        2, vaddfpCode, pairwise=True)
2701    threeEqualRegInstFp("vpadd", "VpaddQFp", "SimdFloatAddOp", ("float",),
2702                        4, vaddfpCode, pairwise=True)
2703
2704    vsubfpCode = '''
2705        FPSCR fpscr = (FPSCR) FpscrExc;
2706        destReg = binaryOp(fpscr, srcReg1, srcReg2, fpSubS,
2707                           true, true, VfpRoundNearest);
2708        FpscrExc = fpscr;
2709    '''
2710    threeEqualRegInstFp("vsub", "VsubDFp", "SimdFloatAddOp", ("float",), 2, vsubfpCode)
2711    threeEqualRegInstFp("vsub", "VsubQFp", "SimdFloatAddOp", ("float",), 4, vsubfpCode)
2712
2713    vmulfpCode = '''
2714        FPSCR fpscr = (FPSCR) FpscrExc;
2715        destReg = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
2716                           true, true, VfpRoundNearest);
2717        FpscrExc = fpscr;
2718    '''
2719    threeEqualRegInstFp("vmul", "NVmulDFp", "SimdFloatMultOp", ("float",), 2, vmulfpCode)
2720    threeEqualRegInstFp("vmul", "NVmulQFp", "SimdFloatMultOp", ("float",), 4, vmulfpCode)
2721
2722    vmlafpCode = '''
2723        FPSCR fpscr = (FPSCR) FpscrExc;
2724        float mid = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
2725                             true, true, VfpRoundNearest);
2726        destReg = binaryOp(fpscr, mid, destReg, fpAddS,
2727                           true, true, VfpRoundNearest);
2728        FpscrExc = fpscr;
2729    '''
2730    threeEqualRegInstFp("vmla", "NVmlaDFp", "SimdFloatMultAccOp", ("float",), 2, vmlafpCode, True)
2731    threeEqualRegInstFp("vmla", "NVmlaQFp", "SimdFloatMultAccOp", ("float",), 4, vmlafpCode, True)
2732
2733    vfmafpCode = '''
2734        FPSCR fpscr = (FPSCR) FpscrExc;
2735        destReg = ternaryOp(fpscr, srcReg1, srcReg2, destReg, fpMulAdd<float>,
2736                            true, true, VfpRoundNearest);
2737        FpscrExc = fpscr;
2738    '''
2739    threeEqualRegInstFp("vfma", "NVfmaDFp", "SimdFloatMultAccOp", ("float",), 2, vfmafpCode, True)
2740    threeEqualRegInstFp("vfma", "NVfmaQFp", "SimdFloatMultAccOp", ("float",), 4, vfmafpCode, True)
2741
2742    vfmsfpCode = '''
2743        FPSCR fpscr = (FPSCR) FpscrExc;
2744        destReg = ternaryOp(fpscr, -srcReg1, srcReg2, destReg, fpMulAdd<float>,
2745                            true, true, VfpRoundNearest);
2746        FpscrExc = fpscr;
2747    '''
2748    threeEqualRegInstFp("vfms", "NVfmsDFp", "SimdFloatMultAccOp", ("float",), 2, vfmsfpCode, True)
2749    threeEqualRegInstFp("vfms", "NVfmsQFp", "SimdFloatMultAccOp", ("float",), 4, vfmsfpCode, True)
2750
2751    vmlsfpCode = '''
2752        FPSCR fpscr = (FPSCR) FpscrExc;
2753        float mid = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
2754                             true, true, VfpRoundNearest);
2755        destReg = binaryOp(fpscr, destReg, mid, fpSubS,
2756                           true, true, VfpRoundNearest);
2757        FpscrExc = fpscr;
2758    '''
2759    threeEqualRegInstFp("vmls", "NVmlsDFp", "SimdFloatMultAccOp", ("float",), 2, vmlsfpCode, True)
2760    threeEqualRegInstFp("vmls", "NVmlsQFp", "SimdFloatMultAccOp", ("float",), 4, vmlsfpCode, True)
2761
2762    vcgtfpCode = '''
2763        FPSCR fpscr = (FPSCR) FpscrExc;
2764        float res = binaryOp(fpscr, srcReg1, srcReg2, vcgtFunc,
2765                             true, true, VfpRoundNearest);
2766        destReg = (res == 0) ? -1 : 0;
2767        if (res == 2.0)
2768            fpscr.ioc = 1;
2769        FpscrExc = fpscr;
2770    '''
2771    threeEqualRegInstFp("vcgt", "VcgtDFp", "SimdFloatCmpOp", ("float",),
2772            2, vcgtfpCode, toInt = True)
2773    threeEqualRegInstFp("vcgt", "VcgtQFp", "SimdFloatCmpOp", ("float",),
2774            4, vcgtfpCode, toInt = True)
2775
2776    vcgefpCode = '''
2777        FPSCR fpscr = (FPSCR) FpscrExc;
2778        float res = binaryOp(fpscr, srcReg1, srcReg2, vcgeFunc,
2779                             true, true, VfpRoundNearest);
2780        destReg = (res == 0) ? -1 : 0;
2781        if (res == 2.0)
2782            fpscr.ioc = 1;
2783        FpscrExc = fpscr;
2784    '''
2785    threeEqualRegInstFp("vcge", "VcgeDFp", "SimdFloatCmpOp", ("float",),
2786            2, vcgefpCode, toInt = True)
2787    threeEqualRegInstFp("vcge", "VcgeQFp", "SimdFloatCmpOp", ("float",),
2788            4, vcgefpCode, toInt = True)
2789
2790    vacgtfpCode = '''
2791        FPSCR fpscr = (FPSCR) FpscrExc;
2792        float res = binaryOp(fpscr, srcReg1, srcReg2, vacgtFunc,
2793                             true, true, VfpRoundNearest);
2794        destReg = (res == 0) ? -1 : 0;
2795        if (res == 2.0)
2796            fpscr.ioc = 1;
2797        FpscrExc = fpscr;
2798    '''
2799    threeEqualRegInstFp("vacgt", "VacgtDFp", "SimdFloatCmpOp", ("float",),
2800            2, vacgtfpCode, toInt = True)
2801    threeEqualRegInstFp("vacgt", "VacgtQFp", "SimdFloatCmpOp", ("float",),
2802            4, vacgtfpCode, toInt = True)
2803
2804    vacgefpCode = '''
2805        FPSCR fpscr = (FPSCR) FpscrExc;
2806        float res = binaryOp(fpscr, srcReg1, srcReg2, vacgeFunc,
2807                             true, true, VfpRoundNearest);
2808        destReg = (res == 0) ? -1 : 0;
2809        if (res == 2.0)
2810            fpscr.ioc = 1;
2811        FpscrExc = fpscr;
2812    '''
2813    threeEqualRegInstFp("vacge", "VacgeDFp", "SimdFloatCmpOp", ("float",),
2814            2, vacgefpCode, toInt = True)
2815    threeEqualRegInstFp("vacge", "VacgeQFp", "SimdFloatCmpOp", ("float",),
2816            4, vacgefpCode, toInt = True)
2817
2818    vceqfpCode = '''
2819        FPSCR fpscr = (FPSCR) FpscrExc;
2820        float res = binaryOp(fpscr, srcReg1, srcReg2, vceqFunc,
2821                             true, true, VfpRoundNearest);
2822        destReg = (res == 0) ? -1 : 0;
2823        if (res == 2.0)
2824            fpscr.ioc = 1;
2825        FpscrExc = fpscr;
2826    '''
2827    threeEqualRegInstFp("vceq", "VceqDFp", "SimdFloatCmpOp", ("float",),
2828            2, vceqfpCode, toInt = True)
2829    threeEqualRegInstFp("vceq", "VceqQFp", "SimdFloatCmpOp", ("float",),
2830            4, vceqfpCode, toInt = True)
2831
2832    vrecpsCode = '''
2833        FPSCR fpscr = (FPSCR) FpscrExc;
2834        destReg = binaryOp(fpscr, srcReg1, srcReg2, fpRecpsS,
2835                           true, true, VfpRoundNearest);
2836        FpscrExc = fpscr;
2837    '''
2838    threeEqualRegInstFp("vrecps", "VrecpsDFp", "SimdFloatMultAccOp", ("float",), 2, vrecpsCode)
2839    threeEqualRegInstFp("vrecps", "VrecpsQFp", "SimdFloatMultAccOp", ("float",), 4, vrecpsCode)
2840
2841    vrsqrtsCode = '''
2842        FPSCR fpscr = (FPSCR) FpscrExc;
2843        destReg = binaryOp(fpscr, srcReg1, srcReg2, fpRSqrtsS,
2844                           true, true, VfpRoundNearest);
2845        FpscrExc = fpscr;
2846    '''
2847    threeEqualRegInstFp("vrsqrts", "VrsqrtsDFp", "SimdFloatMiscOp", ("float",), 2, vrsqrtsCode)
2848    threeEqualRegInstFp("vrsqrts", "VrsqrtsQFp", "SimdFloatMiscOp", ("float",), 4, vrsqrtsCode)
2849
2850    vabdfpCode = '''
2851        FPSCR fpscr = (FPSCR) FpscrExc;
2852        float mid = binaryOp(fpscr, srcReg1, srcReg2, fpSubS,
2853                             true, true, VfpRoundNearest);
2854        destReg = fabs(mid);
2855        FpscrExc = fpscr;
2856    '''
2857    threeEqualRegInstFp("vabd", "VabdDFp", "SimdFloatAddOp", ("float",), 2, vabdfpCode)
2858    threeEqualRegInstFp("vabd", "VabdQFp", "SimdFloatAddOp", ("float",), 4, vabdfpCode)
2859
2860    twoEqualRegInst("vmla", "VmlasD", "SimdMultAccOp", unsignedTypes, 2, vmlaCode, True)
2861    twoEqualRegInst("vmla", "VmlasQ", "SimdMultAccOp", unsignedTypes, 4, vmlaCode, True)
2862    twoEqualRegInstFp("vmla", "VmlasDFp", "SimdFloatMultAccOp", ("float",), 2, vmlafpCode, True)
2863    twoEqualRegInstFp("vmla", "VmlasQFp", "SimdFloatMultAccOp", ("float",), 4, vmlafpCode, True)
2864    twoRegLongInst("vmlal", "Vmlals", "SimdMultAccOp", smallTypes, vmlalCode, True)
2865
2866    twoEqualRegInst("vmls", "VmlssD", "SimdMultAccOp", allTypes, 2, vmlsCode, True)
2867    twoEqualRegInst("vmls", "VmlssQ", "SimdMultAccOp", allTypes, 4, vmlsCode, True)
2868    twoEqualRegInstFp("vmls", "VmlssDFp", "SimdFloatMultAccOp", ("float",), 2, vmlsfpCode, True)
2869    twoEqualRegInstFp("vmls", "VmlssQFp", "SimdFloatMultAccOp", ("float",), 4, vmlsfpCode, True)
2870    twoRegLongInst("vmlsl", "Vmlsls", "SimdMultAccOp", smallTypes, vmlslCode, True)
2871
2872    twoEqualRegInst("vmul", "VmulsD", "SimdMultOp", allTypes, 2, vmulCode)
2873    twoEqualRegInst("vmul", "VmulsQ", "SimdMultOp", allTypes, 4, vmulCode)
2874    twoEqualRegInstFp("vmul", "VmulsDFp", "SimdFloatMultOp", ("float",), 2, vmulfpCode)
2875    twoEqualRegInstFp("vmul", "VmulsQFp", "SimdFloatMultOp", ("float",), 4, vmulfpCode)
2876    twoRegLongInst("vmull", "Vmulls", "SimdMultOp", smallTypes, vmullCode)
2877
2878    twoRegLongInst("vqdmull", "Vqdmulls", "SimdMultOp", smallTypes, vqdmullCode)
2879    twoRegLongInst("vqdmlal", "Vqdmlals", "SimdMultAccOp", smallTypes, vqdmlalCode, True)
2880    twoRegLongInst("vqdmlsl", "Vqdmlsls", "SimdMultAccOp", smallTypes, vqdmlslCode, True)
2881    twoEqualRegInst("vqdmulh", "VqdmulhsD", "SimdMultOp", smallSignedTypes, 2, vqdmulhCode)
2882    twoEqualRegInst("vqdmulh", "VqdmulhsQ", "SimdMultOp", smallSignedTypes, 4, vqdmulhCode)
2883    twoEqualRegInst("vqrdmulh", "VqrdmulhsD",
2884            "SimdMultOp", smallSignedTypes, 2, vqrdmulhCode)
2885    twoEqualRegInst("vqrdmulh", "VqrdmulhsQ",
2886            "SimdMultOp", smallSignedTypes, 4, vqrdmulhCode)
2887
2888    vshrCode = '''
2889        if (imm >= sizeof(srcElem1) * 8) {
2890            if (ltz(srcElem1))
2891                destElem = -1;
2892            else
2893                destElem = 0;
2894        } else {
2895            destElem = srcElem1 >> imm;
2896        }
2897    '''
2898    twoRegShiftInst("vshr", "NVshrD", "SimdShiftOp", allTypes, 2, vshrCode)
2899    twoRegShiftInst("vshr", "NVshrQ", "SimdShiftOp", allTypes, 4, vshrCode)
2900
2901    vsraCode = '''
2902        Element mid;;
2903        if (imm >= sizeof(srcElem1) * 8) {
2904            mid = ltz(srcElem1) ? -1 : 0;
2905        } else {
2906            mid = srcElem1 >> imm;
2907            if (ltz(srcElem1) && !ltz(mid)) {
2908                mid |= -(mid & ((Element)1 <<
2909                            (sizeof(Element) * 8 - 1 - imm)));
2910            }
2911        }
2912        destElem += mid;
2913    '''
2914    twoRegShiftInst("vsra", "NVsraD", "SimdShiftAccOp", allTypes, 2, vsraCode, True)
2915    twoRegShiftInst("vsra", "NVsraQ", "SimdShiftAccOp", allTypes, 4, vsraCode, True)
2916
2917    vrshrCode = '''
2918        if (imm > sizeof(srcElem1) * 8) {
2919            destElem = 0;
2920        } else if (imm) {
2921            Element rBit = bits(srcElem1, imm - 1);
2922            destElem = ((srcElem1 >> (imm - 1)) >> 1) + rBit;
2923        } else {
2924            destElem = srcElem1;
2925        }
2926    '''
2927    twoRegShiftInst("vrshr", "NVrshrD", "SimdShiftOp", allTypes, 2, vrshrCode)
2928    twoRegShiftInst("vrshr", "NVrshrQ", "SimdShiftOp", allTypes, 4, vrshrCode)
2929
2930    vrsraCode = '''
2931        if (imm > sizeof(srcElem1) * 8) {
2932            destElem += 0;
2933        } else if (imm) {
2934            Element rBit = bits(srcElem1, imm - 1);
2935            destElem += ((srcElem1 >> (imm - 1)) >> 1) + rBit;
2936        } else {
2937            destElem += srcElem1;
2938        }
2939    '''
2940    twoRegShiftInst("vrsra", "NVrsraD", "SimdShiftAccOp", allTypes, 2, vrsraCode, True)
2941    twoRegShiftInst("vrsra", "NVrsraQ", "SimdShiftAccOp", allTypes, 4, vrsraCode, True)
2942
2943    vsriCode = '''
2944        if (imm >= sizeof(Element) * 8) {
2945            destElem = destElem;
2946        } else {
2947            destElem = (srcElem1 >> imm) |
2948                (destElem & ~mask(sizeof(Element) * 8 - imm));
2949        }
2950    '''
2951    twoRegShiftInst("vsri", "NVsriD", "SimdShiftOp", unsignedTypes, 2, vsriCode, True)
2952    twoRegShiftInst("vsri", "NVsriQ", "SimdShiftOp", unsignedTypes, 4, vsriCode, True)
2953
2954    vshlCode = '''
2955        if (imm >= sizeof(Element) * 8) {
2956            destElem = (srcElem1 << (sizeof(Element) * 8 - 1)) << 1;
2957        } else {
2958            destElem = srcElem1 << imm;
2959        }
2960    '''
2961    twoRegShiftInst("vshl", "NVshlD", "SimdShiftOp", unsignedTypes, 2, vshlCode)
2962    twoRegShiftInst("vshl", "NVshlQ", "SimdShiftOp", unsignedTypes, 4, vshlCode)
2963
2964    vsliCode = '''
2965        if (imm >= sizeof(Element) * 8) {
2966            destElem = destElem;
2967        } else {
2968            destElem = (srcElem1 << imm) | (destElem & mask(imm));
2969        }
2970    '''
2971    twoRegShiftInst("vsli", "NVsliD", "SimdShiftOp", unsignedTypes, 2, vsliCode, True)
2972    twoRegShiftInst("vsli", "NVsliQ", "SimdShiftOp", unsignedTypes, 4, vsliCode, True)
2973
2974    vqshlCode = '''
2975        FPSCR fpscr = (FPSCR) FpscrQc;
2976        if (imm >= sizeof(Element) * 8) {
2977            if (srcElem1 != 0) {
2978                destElem = std::numeric_limits<Element>::min();
2979                if (srcElem1 > 0)
2980                    destElem = ~destElem;
2981                fpscr.qc = 1;
2982            } else {
2983                destElem = 0;
2984            }
2985        } else if (imm) {
2986            destElem = (srcElem1 << imm);
2987            uint64_t topBits = bits((uint64_t)srcElem1,
2988                                    sizeof(Element) * 8 - 1,
2989                                    sizeof(Element) * 8 - 1 - imm);
2990            if (topBits != 0 && topBits != mask(imm + 1)) {
2991                destElem = std::numeric_limits<Element>::min();
2992                if (srcElem1 > 0)
2993                    destElem = ~destElem;
2994                fpscr.qc = 1;
2995            }
2996        } else {
2997            destElem = srcElem1;
2998        }
2999        FpscrQc = fpscr;
3000    '''
3001    twoRegShiftInst("vqshl", "NVqshlD", "SimdShiftOp", signedTypes, 2, vqshlCode)
3002    twoRegShiftInst("vqshl", "NVqshlQ", "SimdShiftOp", signedTypes, 4, vqshlCode)
3003
3004    vqshluCode = '''
3005        FPSCR fpscr = (FPSCR) FpscrQc;
3006        if (imm >= sizeof(Element) * 8) {
3007            if (srcElem1 != 0) {
3008                destElem = mask(sizeof(Element) * 8);
3009                fpscr.qc = 1;
3010            } else {
3011                destElem = 0;
3012            }
3013        } else if (imm) {
3014            destElem = (srcElem1 << imm);
3015            uint64_t topBits = bits((uint64_t)srcElem1,
3016                                    sizeof(Element) * 8 - 1,
3017                                    sizeof(Element) * 8 - imm);
3018            if (topBits != 0) {
3019                destElem = mask(sizeof(Element) * 8);
3020                fpscr.qc = 1;
3021            }
3022        } else {
3023            destElem = srcElem1;
3024        }
3025        FpscrQc = fpscr;
3026    '''
3027    twoRegShiftInst("vqshlu", "NVqshluD", "SimdShiftOp", unsignedTypes, 2, vqshluCode)
3028    twoRegShiftInst("vqshlu", "NVqshluQ", "SimdShiftOp", unsignedTypes, 4, vqshluCode)
3029
3030    vqshlusCode = '''
3031        FPSCR fpscr = (FPSCR) FpscrQc;
3032        if (imm >= sizeof(Element) * 8) {
3033            if (srcElem1 < 0) {
3034                destElem = 0;
3035                fpscr.qc = 1;
3036            } else if (srcElem1 > 0) {
3037                destElem = mask(sizeof(Element) * 8);
3038                fpscr.qc = 1;
3039            } else {
3040                destElem = 0;
3041            }
3042        } else if (imm) {
3043            destElem = (srcElem1 << imm);
3044            uint64_t topBits = bits((uint64_t)srcElem1,
3045                                    sizeof(Element) * 8 - 1,
3046                                    sizeof(Element) * 8 - imm);
3047            if (srcElem1 < 0) {
3048                destElem = 0;
3049                fpscr.qc = 1;
3050            } else if (topBits != 0) {
3051                destElem = mask(sizeof(Element) * 8);
3052                fpscr.qc = 1;
3053            }
3054        } else {
3055            if (srcElem1 < 0) {
3056                fpscr.qc = 1;
3057                destElem = 0;
3058            } else {
3059                destElem = srcElem1;
3060            }
3061        }
3062        FpscrQc = fpscr;
3063    '''
3064    twoRegShiftInst("vqshlus", "NVqshlusD", "SimdShiftOp", signedTypes, 2, vqshlusCode)
3065    twoRegShiftInst("vqshlus", "NVqshlusQ", "SimdShiftOp", signedTypes, 4, vqshlusCode)
3066
3067    vshrnCode = '''
3068        if (imm >= sizeof(srcElem1) * 8) {
3069            destElem = 0;
3070        } else {
3071            destElem = srcElem1 >> imm;
3072        }
3073    '''
3074    twoRegNarrowShiftInst("vshrn", "NVshrn", "SimdShiftOp", smallUnsignedTypes, vshrnCode)
3075
3076    vrshrnCode = '''
3077        if (imm > sizeof(srcElem1) * 8) {
3078            destElem = 0;
3079        } else if (imm) {
3080            Element rBit = bits(srcElem1, imm - 1);
3081            destElem = ((srcElem1 >> (imm - 1)) >> 1) + rBit;
3082        } else {
3083            destElem = srcElem1;
3084        }
3085    '''
3086    twoRegNarrowShiftInst("vrshrn", "NVrshrn", "SimdShiftOp", smallUnsignedTypes, vrshrnCode)
3087
3088    vqshrnCode = '''
3089        FPSCR fpscr = (FPSCR) FpscrQc;
3090        if (imm > sizeof(srcElem1) * 8) {
3091            if (srcElem1 != 0 && srcElem1 != -1)
3092                fpscr.qc = 1;
3093            destElem = 0;
3094        } else if (imm) {
3095            BigElement mid = ((srcElem1 >> (imm - 1)) >> 1);
3096            mid |= -(mid & ((BigElement)1 <<
3097                        (sizeof(BigElement) * 8 - 1 - imm)));
3098            if (mid != (Element)mid) {
3099                destElem = mask(sizeof(Element) * 8 - 1);
3100                if (srcElem1 < 0)
3101                    destElem = ~destElem;
3102                fpscr.qc = 1;
3103            } else {
3104                destElem = mid;
3105            }
3106        } else {
3107            destElem = srcElem1;
3108        }
3109        FpscrQc = fpscr;
3110    '''
3111    twoRegNarrowShiftInst("vqshrn", "NVqshrn", "SimdShiftOp", smallSignedTypes, vqshrnCode)
3112
3113    vqshrunCode = '''
3114        FPSCR fpscr = (FPSCR) FpscrQc;
3115        if (imm > sizeof(srcElem1) * 8) {
3116            if (srcElem1 != 0)
3117                fpscr.qc = 1;
3118            destElem = 0;
3119        } else if (imm) {
3120            BigElement mid = ((srcElem1 >> (imm - 1)) >> 1);
3121            if (mid != (Element)mid) {
3122                destElem = mask(sizeof(Element) * 8);
3123                fpscr.qc = 1;
3124            } else {
3125                destElem = mid;
3126            }
3127        } else {
3128            destElem = srcElem1;
3129        }
3130        FpscrQc = fpscr;
3131    '''
3132    twoRegNarrowShiftInst("vqshrun", "NVqshrun",
3133                          "SimdShiftOp", smallUnsignedTypes, vqshrunCode)
3134
3135    vqshrunsCode = '''
3136        FPSCR fpscr = (FPSCR) FpscrQc;
3137        if (imm > sizeof(srcElem1) * 8) {
3138            if (srcElem1 != 0)
3139                fpscr.qc = 1;
3140            destElem = 0;
3141        } else if (imm) {
3142            BigElement mid = ((srcElem1 >> (imm - 1)) >> 1);
3143            if (bits(mid, sizeof(BigElement) * 8 - 1,
3144                          sizeof(Element) * 8) != 0) {
3145                if (srcElem1 < 0) {
3146                    destElem = 0;
3147                } else {
3148                    destElem = mask(sizeof(Element) * 8);
3149                }
3150                fpscr.qc = 1;
3151            } else {
3152                destElem = mid;
3153            }
3154        } else {
3155            destElem = srcElem1;
3156        }
3157        FpscrQc = fpscr;
3158    '''
3159    twoRegNarrowShiftInst("vqshrun", "NVqshruns",
3160                          "SimdShiftOp", smallSignedTypes, vqshrunsCode)
3161
3162    vqrshrnCode = '''
3163        FPSCR fpscr = (FPSCR) FpscrQc;
3164        if (imm > sizeof(srcElem1) * 8) {
3165            if (srcElem1 != 0 && srcElem1 != -1)
3166                fpscr.qc = 1;
3167            destElem = 0;
3168        } else if (imm) {
3169            BigElement mid = (srcElem1 >> (imm - 1));
3170            uint64_t rBit = mid & 0x1;
3171            mid >>= 1;
3172            mid |= -(mid & ((BigElement)1 <<
3173                        (sizeof(BigElement) * 8 - 1 - imm)));
3174            mid += rBit;
3175            if (mid != (Element)mid) {
3176                destElem = mask(sizeof(Element) * 8 - 1);
3177                if (srcElem1 < 0)
3178                    destElem = ~destElem;
3179                fpscr.qc = 1;
3180            } else {
3181                destElem = mid;
3182            }
3183        } else {
3184            if (srcElem1 != (Element)srcElem1) {
3185                destElem = mask(sizeof(Element) * 8 - 1);
3186                if (srcElem1 < 0)
3187                    destElem = ~destElem;
3188                fpscr.qc = 1;
3189            } else {
3190                destElem = srcElem1;
3191            }
3192        }
3193        FpscrQc = fpscr;
3194    '''
3195    twoRegNarrowShiftInst("vqrshrn", "NVqrshrn",
3196                          "SimdShiftOp", smallSignedTypes, vqrshrnCode)
3197
3198    vqrshrunCode = '''
3199        FPSCR fpscr = (FPSCR) FpscrQc;
3200        if (imm > sizeof(srcElem1) * 8) {
3201            if (srcElem1 != 0)
3202                fpscr.qc = 1;
3203            destElem = 0;
3204        } else if (imm) {
3205            BigElement mid = (srcElem1 >> (imm - 1));
3206            uint64_t rBit = mid & 0x1;
3207            mid >>= 1;
3208            mid += rBit;
3209            if (mid != (Element)mid) {
3210                destElem = mask(sizeof(Element) * 8);
3211                fpscr.qc = 1;
3212            } else {
3213                destElem = mid;
3214            }
3215        } else {
3216            if (srcElem1 != (Element)srcElem1) {
3217                destElem = mask(sizeof(Element) * 8 - 1);
3218                fpscr.qc = 1;
3219            } else {
3220                destElem = srcElem1;
3221            }
3222        }
3223        FpscrQc = fpscr;
3224    '''
3225    twoRegNarrowShiftInst("vqrshrun", "NVqrshrun",
3226                          "SimdShiftOp", smallUnsignedTypes, vqrshrunCode)
3227
3228    vqrshrunsCode = '''
3229        FPSCR fpscr = (FPSCR) FpscrQc;
3230        if (imm > sizeof(srcElem1) * 8) {
3231            if (srcElem1 != 0)
3232                fpscr.qc = 1;
3233            destElem = 0;
3234        } else if (imm) {
3235            BigElement mid = (srcElem1 >> (imm - 1));
3236            uint64_t rBit = mid & 0x1;
3237            mid >>= 1;
3238            mid |= -(mid & ((BigElement)1 <<
3239                            (sizeof(BigElement) * 8 - 1 - imm)));
3240            mid += rBit;
3241            if (bits(mid, sizeof(BigElement) * 8 - 1,
3242                          sizeof(Element) * 8) != 0) {
3243                if (srcElem1 < 0) {
3244                    destElem = 0;
3245                } else {
3246                    destElem = mask(sizeof(Element) * 8);
3247                }
3248                fpscr.qc = 1;
3249            } else {
3250                destElem = mid;
3251            }
3252        } else {
3253            if (srcElem1 < 0) {
3254                fpscr.qc = 1;
3255                destElem = 0;
3256            } else {
3257                destElem = srcElem1;
3258            }
3259        }
3260        FpscrQc = fpscr;
3261    '''
3262    twoRegNarrowShiftInst("vqrshrun", "NVqrshruns",
3263                          "SimdShiftOp", smallSignedTypes, vqrshrunsCode)
3264
3265    vshllCode = '''
3266        if (imm >= sizeof(destElem) * 8) {
3267            destElem = 0;
3268        } else {
3269            destElem = (BigElement)srcElem1 << imm;
3270        }
3271    '''
3272    twoRegLongShiftInst("vshll", "NVshll", "SimdShiftOp", smallTypes, vshllCode)
3273
3274    vmovlCode = '''
3275        destElem = srcElem1;
3276    '''
3277    twoRegLongShiftInst("vmovl", "NVmovl", "SimdMiscOp", smallTypes, vmovlCode)
3278
3279    vcvt2ufxCode = '''
3280        FPSCR fpscr = (FPSCR) FpscrExc;
3281        if (flushToZero(srcElem1))
3282            fpscr.idc = 1;
3283        VfpSavedState state = prepFpState(VfpRoundNearest);
3284        __asm__ __volatile__("" : "=m" (srcElem1) : "m" (srcElem1));
3285        destReg = vfpFpToFixed<float>(srcElem1, false, 32, imm);
3286        __asm__ __volatile__("" :: "m" (destReg));
3287        finishVfp(fpscr, state, true);
3288        FpscrExc = fpscr;
3289    '''
3290    twoRegShiftInst("vcvt", "NVcvt2ufxD", "SimdCvtOp", ("float",),
3291            2, vcvt2ufxCode, toInt = True)
3292    twoRegShiftInst("vcvt", "NVcvt2ufxQ", "SimdCvtOp", ("float",),
3293            4, vcvt2ufxCode, toInt = True)
3294
3295    vcvt2sfxCode = '''
3296        FPSCR fpscr = (FPSCR) FpscrExc;
3297        if (flushToZero(srcElem1))
3298            fpscr.idc = 1;
3299        VfpSavedState state = prepFpState(VfpRoundNearest);
3300        __asm__ __volatile__("" : "=m" (srcElem1) : "m" (srcElem1));
3301        destReg = vfpFpToFixed<float>(srcElem1, true, 32, imm);
3302        __asm__ __volatile__("" :: "m" (destReg));
3303        finishVfp(fpscr, state, true);
3304        FpscrExc = fpscr;
3305    '''
3306    twoRegShiftInst("vcvt", "NVcvt2sfxD", "SimdCvtOp", ("float",),
3307            2, vcvt2sfxCode, toInt = True)
3308    twoRegShiftInst("vcvt", "NVcvt2sfxQ", "SimdCvtOp", ("float",),
3309            4, vcvt2sfxCode, toInt = True)
3310
3311    vcvtu2fpCode = '''
3312        FPSCR fpscr = (FPSCR) FpscrExc;
3313        VfpSavedState state = prepFpState(VfpRoundNearest);
3314        __asm__ __volatile__("" : "=m" (srcReg1) : "m" (srcReg1));
3315        destElem = vfpUFixedToFpS(true, true, srcReg1, 32, imm);
3316        __asm__ __volatile__("" :: "m" (destElem));
3317        finishVfp(fpscr, state, true);
3318        FpscrExc = fpscr;
3319    '''
3320    twoRegShiftInst("vcvt", "NVcvtu2fpD", "SimdCvtOp", ("float",),
3321            2, vcvtu2fpCode, fromInt = True)
3322    twoRegShiftInst("vcvt", "NVcvtu2fpQ", "SimdCvtOp", ("float",),
3323            4, vcvtu2fpCode, fromInt = True)
3324
3325    vcvts2fpCode = '''
3326        FPSCR fpscr = (FPSCR) FpscrExc;
3327        VfpSavedState state = prepFpState(VfpRoundNearest);
3328        __asm__ __volatile__("" : "=m" (srcReg1) : "m" (srcReg1));
3329        destElem = vfpSFixedToFpS(true, true, srcReg1, 32, imm);
3330        __asm__ __volatile__("" :: "m" (destElem));
3331        finishVfp(fpscr, state, true);
3332        FpscrExc = fpscr;
3333    '''
3334    twoRegShiftInst("vcvt", "NVcvts2fpD", "SimdCvtOp", ("float",),
3335            2, vcvts2fpCode, fromInt = True)
3336    twoRegShiftInst("vcvt", "NVcvts2fpQ", "SimdCvtOp", ("float",),
3337            4, vcvts2fpCode, fromInt = True)
3338
3339    vcvts2hCode = '''
3340        destElem = 0;
3341        FPSCR fpscr = (FPSCR) FpscrExc;
3342        float srcFp1 = bitsToFp(srcElem1, (float)0.0);
3343        if (flushToZero(srcFp1))
3344            fpscr.idc = 1;
3345        VfpSavedState state = prepFpState(VfpRoundNearest);
3346        __asm__ __volatile__("" : "=m" (srcFp1), "=m" (destElem)
3347                                : "m" (srcFp1), "m" (destElem));
3348        destElem = vcvtFpSFpH(fpscr, true, true, VfpRoundNearest,
3349                              fpscr.ahp, srcFp1);
3350        __asm__ __volatile__("" :: "m" (destElem));
3351        finishVfp(fpscr, state, true);
3352        FpscrExc = fpscr;
3353    '''
3354    twoRegNarrowMiscInst("vcvt", "NVcvts2h", "SimdCvtOp", ("uint16_t",), vcvts2hCode)
3355
3356    vcvth2sCode = '''
3357        destElem = 0;
3358        FPSCR fpscr = (FPSCR) FpscrExc;
3359        VfpSavedState state = prepFpState(VfpRoundNearest);
3360        __asm__ __volatile__("" : "=m" (srcElem1), "=m" (destElem)
3361                                : "m" (srcElem1), "m" (destElem));
3362        destElem = fpToBits(vcvtFpHFpS(fpscr, true, fpscr.ahp, srcElem1));
3363        __asm__ __volatile__("" :: "m" (destElem));
3364        finishVfp(fpscr, state, true);
3365        FpscrExc = fpscr;
3366    '''
3367    twoRegLongMiscInst("vcvt", "NVcvth2s", "SimdCvtOp", ("uint16_t",), vcvth2sCode)
3368
3369    vrsqrteCode = '''
3370        destElem = unsignedRSqrtEstimate(srcElem1);
3371    '''
3372    twoRegMiscInst("vrsqrte", "NVrsqrteD", "SimdSqrtOp", ("uint32_t",), 2, vrsqrteCode)
3373    twoRegMiscInst("vrsqrte", "NVrsqrteQ", "SimdSqrtOp", ("uint32_t",), 4, vrsqrteCode)
3374
3375    vrsqrtefpCode = '''
3376        FPSCR fpscr = (FPSCR) FpscrExc;
3377        if (flushToZero(srcReg1))
3378            fpscr.idc = 1;
3379        destReg = fprSqrtEstimate(fpscr, srcReg1);
3380        FpscrExc = fpscr;
3381    '''
3382    twoRegMiscInstFp("vrsqrte", "NVrsqrteDFp", "SimdFloatSqrtOp", ("float",), 2, vrsqrtefpCode)
3383    twoRegMiscInstFp("vrsqrte", "NVrsqrteQFp", "SimdFloatSqrtOp", ("float",), 4, vrsqrtefpCode)
3384
3385    vrecpeCode = '''
3386        destElem = unsignedRecipEstimate(srcElem1);
3387    '''
3388    twoRegMiscInst("vrecpe", "NVrecpeD", "SimdMultAccOp", ("uint32_t",), 2, vrecpeCode)
3389    twoRegMiscInst("vrecpe", "NVrecpeQ", "SimdMultAccOp", ("uint32_t",), 4, vrecpeCode)
3390
3391    vrecpefpCode = '''
3392        FPSCR fpscr = (FPSCR) FpscrExc;
3393        if (flushToZero(srcReg1))
3394            fpscr.idc = 1;
3395        destReg = fpRecipEstimate(fpscr, srcReg1);
3396        FpscrExc = fpscr;
3397    '''
3398    twoRegMiscInstFp("vrecpe", "NVrecpeDFp", "SimdFloatMultAccOp", ("float",), 2, vrecpefpCode)
3399    twoRegMiscInstFp("vrecpe", "NVrecpeQFp", "SimdFloatMultAccOp", ("float",), 4, vrecpefpCode)
3400
3401    vrev16Code = '''
3402        destElem = srcElem1;
3403        unsigned groupSize = ((1 << 1) / sizeof(Element));
3404        unsigned reverseMask = (groupSize - 1);
3405        j = i ^ reverseMask;
3406    '''
3407    twoRegMiscInst("vrev16", "NVrev16D", "SimdAluOp", ("uint8_t",), 2, vrev16Code)
3408    twoRegMiscInst("vrev16", "NVrev16Q", "SimdAluOp", ("uint8_t",), 4, vrev16Code)
3409    vrev32Code = '''
3410        destElem = srcElem1;
3411        unsigned groupSize = ((1 << 2) / sizeof(Element));
3412        unsigned reverseMask = (groupSize - 1);
3413        j = i ^ reverseMask;
3414    '''
3415    twoRegMiscInst("vrev32", "NVrev32D",
3416            "SimdAluOp", ("uint8_t", "uint16_t"), 2, vrev32Code)
3417    twoRegMiscInst("vrev32", "NVrev32Q",
3418            "SimdAluOp", ("uint8_t", "uint16_t"), 4, vrev32Code)
3419    vrev64Code = '''
3420        destElem = srcElem1;
3421        unsigned groupSize = ((1 << 3) / sizeof(Element));
3422        unsigned reverseMask = (groupSize - 1);
3423        j = i ^ reverseMask;
3424    '''
3425    twoRegMiscInst("vrev64", "NVrev64D", "SimdAluOp", smallUnsignedTypes, 2, vrev64Code)
3426    twoRegMiscInst("vrev64", "NVrev64Q", "SimdAluOp", smallUnsignedTypes, 4, vrev64Code)
3427
3428    split('exec')
3429    exec_output += vcompares + vcomparesL
3430
3431    vpaddlCode = '''
3432        destElem = (BigElement)srcElem1 + (BigElement)srcElem2;
3433    '''
3434    twoRegCondenseInst("vpaddl", "NVpaddlD", "SimdAddOp", smallTypes, 2, vpaddlCode)
3435    twoRegCondenseInst("vpaddl", "NVpaddlQ", "SimdAddOp", smallTypes, 4, vpaddlCode)
3436
3437    vpadalCode = '''
3438        destElem += (BigElement)srcElem1 + (BigElement)srcElem2;
3439    '''
3440    twoRegCondenseInst("vpadal", "NVpadalD", "SimdAddAccOp", smallTypes, 2, vpadalCode, True)
3441    twoRegCondenseInst("vpadal", "NVpadalQ", "SimdAddAccOp", smallTypes, 4, vpadalCode, True)
3442
3443    vclsCode = '''
3444        unsigned count = 0;
3445        if (srcElem1 < 0) {
3446            srcElem1 <<= 1;
3447            while (srcElem1 < 0 && count < sizeof(Element) * 8 - 1) {
3448                count++;
3449                srcElem1 <<= 1;
3450            }
3451        } else {
3452            srcElem1 <<= 1;
3453            while (srcElem1 >= 0 && count < sizeof(Element) * 8 - 1) {
3454                count++;
3455                srcElem1 <<= 1;
3456            }
3457        }
3458        destElem = count;
3459    '''
3460    twoRegMiscInst("vcls", "NVclsD", "SimdAluOp", signedTypes, 2, vclsCode)
3461    twoRegMiscInst("vcls", "NVclsQ", "SimdAluOp", signedTypes, 4, vclsCode)
3462
3463    vclzCode = '''
3464        unsigned count = 0;
3465        while (srcElem1 >= 0 && count < sizeof(Element) * 8) {
3466            count++;
3467            srcElem1 <<= 1;
3468        }
3469        destElem = count;
3470    '''
3471    twoRegMiscInst("vclz", "NVclzD", "SimdAluOp", signedTypes, 2, vclzCode)
3472    twoRegMiscInst("vclz", "NVclzQ", "SimdAluOp", signedTypes, 4, vclzCode)
3473
3474    vcntCode = '''
3475        unsigned count = 0;
3476        while (srcElem1 && count < sizeof(Element) * 8) {
3477            count += srcElem1 & 0x1;
3478            srcElem1 >>= 1;
3479        }
3480        destElem = count;
3481    '''
3482
3483    twoRegMiscInst("vcnt", "NVcntD", "SimdAluOp", unsignedTypes, 2, vcntCode)
3484    twoRegMiscInst("vcnt", "NVcntQ", "SimdAluOp", unsignedTypes, 4, vcntCode)
3485
3486    vmvnCode = '''
3487        destElem = ~srcElem1;
3488    '''
3489    twoRegMiscInst("vmvn", "NVmvnD", "SimdAluOp", ("uint64_t",), 2, vmvnCode)
3490    twoRegMiscInst("vmvn", "NVmvnQ", "SimdAluOp", ("uint64_t",), 4, vmvnCode)
3491
3492    vqabsCode = '''
3493        FPSCR fpscr = (FPSCR) FpscrQc;
3494        if (srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
3495            fpscr.qc = 1;
3496            destElem = ~srcElem1;
3497        } else if (srcElem1 < 0) {
3498            destElem = -srcElem1;
3499        } else {
3500            destElem = srcElem1;
3501        }
3502        FpscrQc = fpscr;
3503    '''
3504    twoRegMiscInst("vqabs", "NVqabsD", "SimdAluOp", signedTypes, 2, vqabsCode)
3505    twoRegMiscInst("vqabs", "NVqabsQ", "SimdAluOp", signedTypes, 4, vqabsCode)
3506
3507    vqnegCode = '''
3508        FPSCR fpscr = (FPSCR) FpscrQc;
3509        if (srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
3510            fpscr.qc = 1;
3511            destElem = ~srcElem1;
3512        } else {
3513            destElem = -srcElem1;
3514        }
3515        FpscrQc = fpscr;
3516    '''
3517    twoRegMiscInst("vqneg", "NVqnegD", "SimdAluOp", signedTypes, 2, vqnegCode)
3518    twoRegMiscInst("vqneg", "NVqnegQ", "SimdAluOp", signedTypes, 4, vqnegCode)
3519
3520    vabsCode = '''
3521        if (srcElem1 < 0) {
3522            destElem = -srcElem1;
3523        } else {
3524            destElem = srcElem1;
3525        }
3526    '''
3527
3528    twoRegMiscInst("vabs", "NVabsD", "SimdAluOp", signedTypes, 2, vabsCode)
3529    twoRegMiscInst("vabs", "NVabsQ", "SimdAluOp", signedTypes, 4, vabsCode)
3530    vabsfpCode = '''
3531        union
3532        {
3533            uint32_t i;
3534            float f;
3535        } cStruct;
3536        cStruct.f = srcReg1;
3537        cStruct.i &= mask(sizeof(Element) * 8 - 1);
3538        destReg = cStruct.f;
3539    '''
3540    twoRegMiscInstFp("vabs", "NVabsDFp", "SimdFloatAluOp", ("float",), 2, vabsfpCode)
3541    twoRegMiscInstFp("vabs", "NVabsQFp", "SimdFloatAluOp", ("float",), 4, vabsfpCode)
3542
3543    vnegCode = '''
3544        destElem = -srcElem1;
3545    '''
3546    twoRegMiscInst("vneg", "NVnegD", "SimdAluOp", signedTypes, 2, vnegCode)
3547    twoRegMiscInst("vneg", "NVnegQ", "SimdAluOp", signedTypes, 4, vnegCode)
3548    vnegfpCode = '''
3549        destReg = -srcReg1;
3550    '''
3551    twoRegMiscInstFp("vneg", "NVnegDFp", "SimdFloatAluOp", ("float",), 2, vnegfpCode)
3552    twoRegMiscInstFp("vneg", "NVnegQFp", "SimdFloatAluOp", ("float",), 4, vnegfpCode)
3553
3554    vcgtCode = 'destElem = (srcElem1 > 0) ? mask(sizeof(Element) * 8) : 0;'
3555    twoRegMiscInst("vcgt", "NVcgtD", "SimdCmpOp", signedTypes, 2, vcgtCode)
3556    twoRegMiscInst("vcgt", "NVcgtQ", "SimdCmpOp", signedTypes, 4, vcgtCode)
3557    vcgtfpCode = '''
3558        FPSCR fpscr = (FPSCR) FpscrExc;
3559        float res = binaryOp(fpscr, srcReg1, (float)0.0, vcgtFunc,
3560                             true, true, VfpRoundNearest);
3561        destReg = (res == 0) ? -1 : 0;
3562        if (res == 2.0)
3563            fpscr.ioc = 1;
3564        FpscrExc = fpscr;
3565    '''
3566    twoRegMiscInstFp("vcgt", "NVcgtDFp", "SimdFloatCmpOp", ("float",),
3567            2, vcgtfpCode, toInt = True)
3568    twoRegMiscInstFp("vcgt", "NVcgtQFp", "SimdFloatCmpOp", ("float",),
3569            4, vcgtfpCode, toInt = True)
3570
3571    vcgeCode = 'destElem = (srcElem1 >= 0) ? mask(sizeof(Element) * 8) : 0;'
3572    twoRegMiscInst("vcge", "NVcgeD", "SimdCmpOp", signedTypes, 2, vcgeCode)
3573    twoRegMiscInst("vcge", "NVcgeQ", "SimdCmpOp", signedTypes, 4, vcgeCode)
3574    vcgefpCode = '''
3575        FPSCR fpscr = (FPSCR) FpscrExc;
3576        float res = binaryOp(fpscr, srcReg1, (float)0.0, vcgeFunc,
3577                             true, true, VfpRoundNearest);
3578        destReg = (res == 0) ? -1 : 0;
3579        if (res == 2.0)
3580            fpscr.ioc = 1;
3581        FpscrExc = fpscr;
3582    '''
3583    twoRegMiscInstFp("vcge", "NVcgeDFp", "SimdFloatCmpOp", ("float",),
3584            2, vcgefpCode, toInt = True)
3585    twoRegMiscInstFp("vcge", "NVcgeQFp", "SimdFloatCmpOp", ("float",),
3586            4, vcgefpCode, toInt = True)
3587
3588    vceqCode = 'destElem = (srcElem1 == 0) ? mask(sizeof(Element) * 8) : 0;'
3589    twoRegMiscInst("vceq", "NVceqD", "SimdCmpOp", signedTypes, 2, vceqCode)
3590    twoRegMiscInst("vceq", "NVceqQ", "SimdCmpOp", signedTypes, 4, vceqCode)
3591    vceqfpCode = '''
3592        FPSCR fpscr = (FPSCR) FpscrExc;
3593        float res = binaryOp(fpscr, srcReg1, (float)0.0, vceqFunc,
3594                             true, true, VfpRoundNearest);
3595        destReg = (res == 0) ? -1 : 0;
3596        if (res == 2.0)
3597            fpscr.ioc = 1;
3598        FpscrExc = fpscr;
3599    '''
3600    twoRegMiscInstFp("vceq", "NVceqDFp", "SimdFloatCmpOp", ("float",),
3601            2, vceqfpCode, toInt = True)
3602    twoRegMiscInstFp("vceq", "NVceqQFp", "SimdFloatCmpOp", ("float",),
3603            4, vceqfpCode, toInt = True)
3604
3605    vcleCode = 'destElem = (srcElem1 <= 0) ? mask(sizeof(Element) * 8) : 0;'
3606    twoRegMiscInst("vcle", "NVcleD", "SimdCmpOp", signedTypes, 2, vcleCode)
3607    twoRegMiscInst("vcle", "NVcleQ", "SimdCmpOp", signedTypes, 4, vcleCode)
3608    vclefpCode = '''
3609        FPSCR fpscr = (FPSCR) FpscrExc;
3610        float res = binaryOp(fpscr, srcReg1, (float)0.0, vcleFunc,
3611                             true, true, VfpRoundNearest);
3612        destReg = (res == 0) ? -1 : 0;
3613        if (res == 2.0)
3614            fpscr.ioc = 1;
3615        FpscrExc = fpscr;
3616    '''
3617    twoRegMiscInstFp("vcle", "NVcleDFp", "SimdFloatCmpOp", ("float",),
3618            2, vclefpCode, toInt = True)
3619    twoRegMiscInstFp("vcle", "NVcleQFp", "SimdFloatCmpOp", ("float",),
3620            4, vclefpCode, toInt = True)
3621
3622    vcltCode = 'destElem = (srcElem1 < 0) ? mask(sizeof(Element) * 8) : 0;'
3623    twoRegMiscInst("vclt", "NVcltD", "SimdCmpOp", signedTypes, 2, vcltCode)
3624    twoRegMiscInst("vclt", "NVcltQ", "SimdCmpOp", signedTypes, 4, vcltCode)
3625    vcltfpCode = '''
3626        FPSCR fpscr = (FPSCR) FpscrExc;
3627        float res = binaryOp(fpscr, srcReg1, (float)0.0, vcltFunc,
3628                             true, true, VfpRoundNearest);
3629        destReg = (res == 0) ? -1 : 0;
3630        if (res == 2.0)
3631            fpscr.ioc = 1;
3632        FpscrExc = fpscr;
3633    '''
3634    twoRegMiscInstFp("vclt", "NVcltDFp", "SimdFloatCmpOp", ("float",),
3635            2, vcltfpCode, toInt = True)
3636    twoRegMiscInstFp("vclt", "NVcltQFp", "SimdFloatCmpOp", ("float",),
3637            4, vcltfpCode, toInt = True)
3638
3639    vswpCode = '''
3640        uint32_t mid;
3641        for (unsigned r = 0; r < rCount; r++) {
3642            mid = srcReg1.regs[r];
3643            srcReg1.regs[r] = destReg.regs[r];
3644            destReg.regs[r] = mid;
3645        }
3646    '''
3647    twoRegMiscScramble("vswp", "NVswpD", "SimdAluOp", ("uint64_t",), 2, vswpCode)
3648    twoRegMiscScramble("vswp", "NVswpQ", "SimdAluOp", ("uint64_t",), 4, vswpCode)
3649
3650    vtrnCode = '''
3651        Element mid;
3652        for (unsigned i = 0; i < eCount; i += 2) {
3653            mid = srcReg1.elements[i];
3654            srcReg1.elements[i] = destReg.elements[i + 1];
3655            destReg.elements[i + 1] = mid;
3656        }
3657    '''
3658    twoRegMiscScramble("vtrn", "NVtrnD", "SimdAluOp",
3659            smallUnsignedTypes, 2, vtrnCode)
3660    twoRegMiscScramble("vtrn", "NVtrnQ", "SimdAluOp",
3661            smallUnsignedTypes, 4, vtrnCode)
3662
3663    vuzpCode = '''
3664        Element mid[eCount];
3665        memcpy(&mid, &srcReg1, sizeof(srcReg1));
3666        for (unsigned i = 0; i < eCount / 2; i++) {
3667            srcReg1.elements[i] = destReg.elements[2 * i + 1];
3668            srcReg1.elements[eCount / 2 + i] = mid[2 * i + 1];
3669            destReg.elements[i] = destReg.elements[2 * i];
3670        }
3671        for (unsigned i = 0; i < eCount / 2; i++) {
3672            destReg.elements[eCount / 2 + i] = mid[2 * i];
3673        }
3674    '''
3675    twoRegMiscScramble("vuzp", "NVuzpD", "SimdAluOp", unsignedTypes, 2, vuzpCode)
3676    twoRegMiscScramble("vuzp", "NVuzpQ", "SimdAluOp", unsignedTypes, 4, vuzpCode)
3677
3678    vzipCode = '''
3679        Element mid[eCount];
3680        memcpy(&mid, &destReg, sizeof(destReg));
3681        for (unsigned i = 0; i < eCount / 2; i++) {
3682            destReg.elements[2 * i] = mid[i];
3683            destReg.elements[2 * i + 1] = srcReg1.elements[i];
3684        }
3685        for (int i = 0; i < eCount / 2; i++) {
3686            srcReg1.elements[2 * i] = mid[eCount / 2 + i];
3687            srcReg1.elements[2 * i + 1] = srcReg1.elements[eCount / 2 + i];
3688        }
3689    '''
3690    twoRegMiscScramble("vzip", "NVzipD", "SimdAluOp", unsignedTypes, 2, vzipCode)
3691    twoRegMiscScramble("vzip", "NVzipQ", "SimdAluOp", unsignedTypes, 4, vzipCode)
3692
3693    vmovnCode = 'destElem = srcElem1;'
3694    twoRegNarrowMiscInst("vmovn", "NVmovn", "SimdMiscOp", smallUnsignedTypes, vmovnCode)
3695
3696    vdupCode = 'destElem = srcElem1;'
3697    twoRegMiscScInst("vdup", "NVdupD", "SimdAluOp", smallUnsignedTypes, 2, vdupCode)
3698    twoRegMiscScInst("vdup", "NVdupQ", "SimdAluOp", smallUnsignedTypes, 4, vdupCode)
3699
3700    def vdupGprInst(name, Name, opClass, types, rCount):
3701        global header_output, exec_output
3702        eWalkCode = simdEnabledCheckCode + '''
3703        RegVect destReg;
3704        for (unsigned i = 0; i < eCount; i++) {
3705            destReg.elements[i] = htog((Element)Op1);
3706        }
3707        '''
3708        for reg in range(rCount):
3709            eWalkCode += '''
3710            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
3711            ''' % { "reg" : reg }
3712        iop = InstObjParams(name, Name,
3713                            "RegRegOp",
3714                            { "code": eWalkCode,
3715                              "r_count": rCount,
3716                              "predicate_test": predicateTest,
3717                              "op_class": opClass }, [])
3718        header_output += NeonRegRegOpDeclare.subst(iop)
3719        exec_output += NeonEqualRegExecute.subst(iop)
3720        for type in types:
3721            substDict = { "targs" : type,
3722                          "class_name" : Name }
3723            exec_output += NeonExecDeclare.subst(substDict)
3724    vdupGprInst("vdup", "NVdupDGpr", "SimdMiscOp", smallUnsignedTypes, 2)
3725    vdupGprInst("vdup", "NVdupQGpr", "SimdMiscOp", smallUnsignedTypes, 4)
3726
3727    vmovCode = 'destElem = imm;'
3728    oneRegImmInst("vmov", "NVmoviD", "SimdMiscOp", ("uint64_t",), 2, vmovCode)
3729    oneRegImmInst("vmov", "NVmoviQ", "SimdMiscOp", ("uint64_t",), 4, vmovCode)
3730
3731    vorrCode = 'destElem |= imm;'
3732    oneRegImmInst("vorr", "NVorriD", "SimdAluOp", ("uint64_t",), 2, vorrCode, True)
3733    oneRegImmInst("vorr", "NVorriQ", "SimdAluOp", ("uint64_t",), 4, vorrCode, True)
3734
3735    vmvnCode = 'destElem = ~imm;'
3736    oneRegImmInst("vmvn", "NVmvniD", "SimdAluOp", ("uint64_t",), 2, vmvnCode)
3737    oneRegImmInst("vmvn", "NVmvniQ", "SimdAluOp", ("uint64_t",), 4, vmvnCode)
3738
3739    vbicCode = 'destElem &= ~imm;'
3740    oneRegImmInst("vbic", "NVbiciD", "SimdAluOp", ("uint64_t",), 2, vbicCode, True)
3741    oneRegImmInst("vbic", "NVbiciQ", "SimdAluOp", ("uint64_t",), 4, vbicCode, True)
3742
3743    vqmovnCode = '''
3744    FPSCR fpscr = (FPSCR) FpscrQc;
3745    destElem = srcElem1;
3746    if ((BigElement)destElem != srcElem1) {
3747        fpscr.qc = 1;
3748        destElem = mask(sizeof(Element) * 8 - 1);
3749        if (srcElem1 < 0)
3750            destElem = ~destElem;
3751    }
3752    FpscrQc = fpscr;
3753    '''
3754    twoRegNarrowMiscInst("vqmovn", "NVqmovn", "SimdMiscOp", smallSignedTypes, vqmovnCode)
3755
3756    vqmovunCode = '''
3757    FPSCR fpscr = (FPSCR) FpscrQc;
3758    destElem = srcElem1;
3759    if ((BigElement)destElem != srcElem1) {
3760        fpscr.qc = 1;
3761        destElem = mask(sizeof(Element) * 8);
3762    }
3763    FpscrQc = fpscr;
3764    '''
3765    twoRegNarrowMiscInst("vqmovun", "NVqmovun",
3766            "SimdMiscOp", smallUnsignedTypes, vqmovunCode)
3767
3768    vqmovunsCode = '''
3769    FPSCR fpscr = (FPSCR) FpscrQc;
3770    destElem = srcElem1;
3771    if (srcElem1 < 0 ||
3772            ((BigElement)destElem & mask(sizeof(Element) * 8)) != srcElem1) {
3773        fpscr.qc = 1;
3774        destElem = mask(sizeof(Element) * 8);
3775        if (srcElem1 < 0)
3776            destElem = ~destElem;
3777    }
3778    FpscrQc = fpscr;
3779    '''
3780    twoRegNarrowMiscInst("vqmovun", "NVqmovuns",
3781            "SimdMiscOp", smallSignedTypes, vqmovunsCode)
3782
3783    def buildVext(name, Name, opClass, types, rCount, op):
3784        global header_output, exec_output
3785        eWalkCode = simdEnabledCheckCode + '''
3786        RegVect srcReg1, srcReg2, destReg;
3787        '''
3788        for reg in range(rCount):
3789            eWalkCode += '''
3790                srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
3791                srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
3792            ''' % { "reg" : reg }
3793        eWalkCode += op
3794        for reg in range(rCount):
3795            eWalkCode += '''
3796            FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
3797            ''' % { "reg" : reg }
3798        iop = InstObjParams(name, Name,
3799                            "RegRegRegImmOp",
3800                            { "code": eWalkCode,
3801                              "r_count": rCount,
3802                              "predicate_test": predicateTest,
3803                              "op_class": opClass }, [])
3804        header_output += NeonRegRegRegImmOpDeclare.subst(iop)
3805        exec_output += NeonEqualRegExecute.subst(iop)
3806        for type in types:
3807            substDict = { "targs" : type,
3808                          "class_name" : Name }
3809            exec_output += NeonExecDeclare.subst(substDict)
3810
3811    vextCode = '''
3812        for (unsigned i = 0; i < eCount; i++) {
3813            unsigned index = i + imm;
3814            if (index < eCount) {
3815                destReg.elements[i] = srcReg1.elements[index];
3816            } else {
3817                index -= eCount;
3818                if (index >= eCount) {
3819                    fault = std::make_shared<UndefinedInstruction>(machInst,
3820                                                                   false,
3821                                                                   mnemonic);
3822                } else {
3823                    destReg.elements[i] = srcReg2.elements[index];
3824                }
3825            }
3826        }
3827    '''
3828    buildVext("vext", "NVextD", "SimdMiscOp", ("uint8_t",), 2, vextCode)
3829    buildVext("vext", "NVextQ", "SimdMiscOp", ("uint8_t",), 4, vextCode)
3830
3831    def buildVtbxl(name, Name, opClass, length, isVtbl):
3832        global header_output, decoder_output, exec_output
3833        code = simdEnabledCheckCode + '''
3834            union
3835            {
3836                uint8_t bytes[32];
3837                uint32_t regs[8];
3838            } table;
3839
3840            union
3841            {
3842                uint8_t bytes[8];
3843                uint32_t regs[2];
3844            } destReg, srcReg2;
3845
3846            const unsigned length = %(length)d;
3847            const bool isVtbl = %(isVtbl)s;
3848
3849            srcReg2.regs[0] = htog(FpOp2P0_uw);
3850            srcReg2.regs[1] = htog(FpOp2P1_uw);
3851
3852            destReg.regs[0] = htog(FpDestP0_uw);
3853            destReg.regs[1] = htog(FpDestP1_uw);
3854        ''' % { "length" : length, "isVtbl" : isVtbl }
3855        for reg in range(8):
3856            if reg < length * 2:
3857                code += 'table.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);\n' % \
3858                        { "reg" : reg }
3859            else:
3860                code += 'table.regs[%(reg)d] = 0;\n' % { "reg" : reg }
3861        code += '''
3862        for (unsigned i = 0; i < sizeof(destReg); i++) {
3863            uint8_t index = srcReg2.bytes[i];
3864            if (index < 8 * length) {
3865                destReg.bytes[i] = table.bytes[index];
3866            } else {
3867                if (isVtbl)
3868                    destReg.bytes[i] = 0;
3869                // else destReg.bytes[i] unchanged
3870            }
3871        }
3872
3873        FpDestP0_uw = gtoh(destReg.regs[0]);
3874        FpDestP1_uw = gtoh(destReg.regs[1]);
3875        '''
3876        iop = InstObjParams(name, Name,
3877                            "RegRegRegOp",
3878                            { "code": code,
3879                              "predicate_test": predicateTest,
3880                              "op_class": opClass }, [])
3881        header_output += RegRegRegOpDeclare.subst(iop)
3882        decoder_output += RegRegRegOpConstructor.subst(iop)
3883        exec_output += PredOpExecute.subst(iop)
3884
3885    buildVtbxl("vtbl", "NVtbl1", "SimdMiscOp", 1, "true")
3886    buildVtbxl("vtbl", "NVtbl2", "SimdMiscOp", 2, "true")
3887    buildVtbxl("vtbl", "NVtbl3", "SimdMiscOp", 3, "true")
3888    buildVtbxl("vtbl", "NVtbl4", "SimdMiscOp", 4, "true")
3889
3890    buildVtbxl("vtbx", "NVtbx1", "SimdMiscOp", 1, "false")
3891    buildVtbxl("vtbx", "NVtbx2", "SimdMiscOp", 2, "false")
3892    buildVtbxl("vtbx", "NVtbx3", "SimdMiscOp", 3, "false")
3893    buildVtbxl("vtbx", "NVtbx4", "SimdMiscOp", 4, "false")
3894}};
3895