1/*
2 * Copyright (c) 2017-2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Giacomo Gabrielli
38 */
39
40// TODO: add support for suffixes of register specifiers in disasm strings.
41
42#include "arch/arm/insts/sve.hh"
43
44namespace ArmISA {
45
46const char*
47svePredTypeToStr(SvePredType pt)
48{
49    switch (pt) {
50      case SvePredType::MERGE:
51        return "m";
52      case SvePredType::ZERO:
53        return "z";
54      default:
55        return "";
56    }
57}
58
59std::string
60SvePredCountPredOp::generateDisassembly(Addr pc,
61        const SymbolTable *symtab) const
62{
63    std::stringstream ss;
64    printMnemonic(ss, "", false);
65    printIntReg(ss, dest);
66    ccprintf(ss, ", ");
67    printVecPredReg(ss, gp);
68    ccprintf(ss, ", ");
69    printVecPredReg(ss, op1);
70    return ss.str();
71}
72
73std::string
74SvePredCountOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
75{
76    std::stringstream ss;
77    printMnemonic(ss, "", false);
78    if (destIsVec) {
79        printVecReg(ss, dest, true);
80    } else {
81        printIntReg(ss, dest);
82    }
83    ccprintf(ss, ", ");
84    uint8_t opWidth = 64;
85    printVecPredReg(ss, gp);
86    ccprintf(ss, ", ");
87    if (srcIs32b)
88        opWidth = 32;
89    printIntReg(ss, dest, opWidth);
90    return ss.str();
91}
92
93std::string
94SveIndexIIOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
95{
96    std::stringstream ss;
97    printMnemonic(ss, "", false);
98    printVecReg(ss, dest, true);
99    ccprintf(ss, ", #%d, #%d", imm1, imm2);
100    return ss.str();
101}
102
103std::string
104SveIndexIROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
105{
106    std::stringstream ss;
107    printMnemonic(ss, "", false);
108    printVecReg(ss, dest, true);
109    ccprintf(ss, ", #%d, ", imm1);
110    printIntReg(ss, op2);
111    return ss.str();
112}
113
114std::string
115SveIndexRIOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
116{
117    std::stringstream ss;
118    printMnemonic(ss, "", false);
119    printVecReg(ss, dest, true);
120    ccprintf(ss, ", ");
121    printIntReg(ss, op1);
122    ccprintf(ss, ", #%d", imm2);
123    return ss.str();
124}
125
126std::string
127SveIndexRROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
128{
129    std::stringstream ss;
130    printMnemonic(ss, "", false);
131    printVecReg(ss, dest, true);
132    ccprintf(ss, ", ");
133    printIntReg(ss, op1);
134    ccprintf(ss, ", ");
135    printIntReg(ss, op2);
136    return ss.str();
137}
138
139std::string
140SveWhileOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
141{
142    std::stringstream ss;
143    printMnemonic(ss, "", false);
144    printVecPredReg(ss, dest);
145    ccprintf(ss, ", ");
146    uint8_t opWidth;
147    if (srcIs32b)
148        opWidth = 32;
149    else
150        opWidth = 64;
151    printIntReg(ss, op1, opWidth);
152    ccprintf(ss, ", ");
153    printIntReg(ss, op2, opWidth);
154    return ss.str();
155}
156
157std::string
158SveCompTermOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
159{
160    std::stringstream ss;
161    printMnemonic(ss, "", false);
162    printIntReg(ss, op1);
163    ccprintf(ss, ", ");
164    printIntReg(ss, op2);
165    return ss.str();
166}
167
168std::string
169SveUnaryPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
170{
171    std::stringstream ss;
172    printMnemonic(ss, "", false);
173    printVecReg(ss, dest, true);
174    ccprintf(ss, ", ");
175    printVecPredReg(ss, gp);
176    ccprintf(ss, "/m, ");
177    printVecReg(ss, op1, true);
178    return ss.str();
179}
180
181std::string
182SveUnaryUnpredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
183{
184    std::stringstream ss;
185    printMnemonic(ss, "", false);
186    printVecReg(ss, dest, true);
187    ccprintf(ss, ", ");
188    printVecReg(ss, op1, true);
189    return ss.str();
190}
191
192std::string
193SveUnaryWideImmUnpredOp::generateDisassembly(Addr pc,
194                                             const SymbolTable *symtab) const
195{
196    std::stringstream ss;
197    printMnemonic(ss, "", false);
198    printVecReg(ss, dest, true);
199    ccprintf(ss, ", #");
200    ss << imm;
201    return ss.str();
202}
203
204std::string
205SveUnaryWideImmPredOp::generateDisassembly(Addr pc,
206                                           const SymbolTable *symtab) const
207{
208    std::stringstream ss;
209    printMnemonic(ss, "", false);
210    printVecReg(ss, dest, true);
211    ccprintf(ss, ", ");
212    printVecPredReg(ss, gp);
213    ccprintf(ss, (isMerging ? "/m" : "/z"));
214    ccprintf(ss, ", #");
215    ss << imm;
216    return ss.str();
217}
218
219std::string
220SveBinImmUnpredConstrOp::generateDisassembly(Addr pc,
221        const SymbolTable *symtab) const
222{
223    std::stringstream ss;
224    printMnemonic(ss, "", false);
225    printVecReg(ss, dest, true);
226    ccprintf(ss, ", ");
227    printVecPredReg(ss, op1);
228    ccprintf(ss, ", #");
229    ss << imm;
230    return ss.str();
231}
232
233std::string
234SveBinImmPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
235{
236    std::stringstream ss;
237    printMnemonic(ss, "", false);
238    printVecReg(ss, dest, true);
239    ccprintf(ss, ", ");
240    printVecPredReg(ss, gp);
241    ccprintf(ss, "/m, ");
242    printVecReg(ss, dest, true);
243    ccprintf(ss, ", #");
244    ss << imm;
245    return ss.str();
246}
247
248std::string
249SveBinWideImmUnpredOp::generateDisassembly(Addr pc,
250                                           const SymbolTable *symtab) const
251{
252    std::stringstream ss;
253    printMnemonic(ss, "", false);
254    printVecReg(ss, dest, true);
255    ccprintf(ss, ", ");
256    printVecReg(ss, dest, true);
257    ccprintf(ss, ", #");
258    ss << imm;
259    return ss.str();
260}
261
262std::string
263SveBinDestrPredOp::generateDisassembly(Addr pc,
264                                       const SymbolTable *symtab) const
265{
266    std::stringstream ss;
267    printMnemonic(ss, "", false);
268    printVecReg(ss, dest, true);
269    ccprintf(ss, ", ");
270    printVecPredReg(ss, gp);
271    ccprintf(ss, "/m, ");
272    printVecReg(ss, dest, true);
273    ccprintf(ss, ", ");
274    printVecReg(ss, op2, true);
275    return ss.str();
276}
277
278std::string
279SveBinConstrPredOp::generateDisassembly(Addr pc,
280                                        const SymbolTable *symtab) const
281{
282    std::stringstream ss;
283    printMnemonic(ss, "", false);
284    printVecReg(ss, dest, true);
285    ccprintf(ss, ", ");
286    printVecPredReg(ss, gp);
287    if (predType == SvePredType::MERGE || predType == SvePredType::ZERO) {
288        ccprintf(ss, "/%s", svePredTypeToStr(predType));
289    }
290    ccprintf(ss, ", ");
291    printVecReg(ss, op1, true);
292    ccprintf(ss, ", ");
293    printVecReg(ss, op2, true);
294    return ss.str();
295}
296
297std::string
298SveBinUnpredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
299{
300    std::stringstream ss;
301    printMnemonic(ss, "", false);
302    printVecReg(ss, dest, true);
303    ccprintf(ss, ", ");
304    printVecReg(ss, op1, true);
305    ccprintf(ss, ", ");
306    printVecReg(ss, op2, true);
307    return ss.str();
308}
309
310std::string
311SveBinIdxUnpredOp::generateDisassembly(Addr pc,
312                                       const SymbolTable *symtab) const
313{
314    std::stringstream ss;
315    printMnemonic(ss, "", false);
316    printVecReg(ss, dest, true);
317    ccprintf(ss, ", ");
318    printVecReg(ss, op1, true);
319    ccprintf(ss, ", ");
320    printVecReg(ss, op2, true);
321    ccprintf(ss, "[");
322    ss << (uint64_t)index;
323    ccprintf(ss, "]");
324    return ss.str();
325}
326
327std::string
328SvePredLogicalOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
329{
330    std::stringstream ss;
331    printMnemonic(ss, "", false);
332    printVecReg(ss, dest, true);
333    ccprintf(ss, ", ");
334    printVecPredReg(ss, gp);
335    if (isSel) {
336        ccprintf(ss, ", ");
337    } else {
338        ccprintf(ss, "/z, ");
339    }
340    printVecPredReg(ss, op1);
341    ccprintf(ss, ", ");
342    printVecPredReg(ss, op2);
343    return ss.str();
344}
345
346std::string
347SvePredBinPermOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
348{
349    std::stringstream ss;
350    printMnemonic(ss, "", false);
351    printVecPredReg(ss, dest);
352    ccprintf(ss, ", ");
353    printVecPredReg(ss, op1);
354    ccprintf(ss, ", ");
355    printVecPredReg(ss, op2);
356    return ss.str();
357}
358
359std::string
360SveCmpOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
361{
362    std::stringstream ss;
363    printMnemonic(ss, "", false);
364    printVecPredReg(ss, dest);
365    ccprintf(ss, ", ");
366    printVecPredReg(ss, gp);
367    ccprintf(ss, "/z, ");
368    printVecReg(ss, op1, true);
369    ccprintf(ss, ", ");
370    printVecReg(ss, op2, true);
371    return ss.str();
372}
373
374std::string
375SveCmpImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
376{
377    std::stringstream ss;
378    printMnemonic(ss, "", false);
379    printVecPredReg(ss, dest);
380    ccprintf(ss, ", ");
381    printVecPredReg(ss, gp);
382    ccprintf(ss, "/z, ");
383    printVecReg(ss, op1, true);
384    ccprintf(ss, ", #");
385    ss << imm;
386    return ss.str();
387}
388
389std::string
390SveTerPredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
391{
392    std::stringstream ss;
393    printMnemonic(ss, "", false);
394    printVecReg(ss, dest, true);
395    ccprintf(ss, ", ");
396    printVecPredReg(ss, gp);
397    ccprintf(ss, "/m, ");
398    printVecReg(ss, op1, true);
399    ccprintf(ss, ", ");
400    printVecReg(ss, op2, true);
401    return ss.str();
402}
403
404std::string
405SveTerImmUnpredOp::generateDisassembly(Addr pc,
406                                       const SymbolTable *symtab) const
407{
408    std::stringstream ss;
409    printMnemonic(ss, "", false);
410    printVecReg(ss, dest, true);
411    ccprintf(ss, ", ");
412    printVecReg(ss, dest, true);
413    ccprintf(ss, ", ");
414    printVecReg(ss, op2, true);
415    ccprintf(ss, ", #");
416    ss << imm;
417    return ss.str();
418}
419
420std::string
421SveReducOp::generateDisassembly(Addr pc,
422                                const SymbolTable *symtab) const
423{
424    std::stringstream ss;
425    printMnemonic(ss, "", false);
426    printFloatReg(ss, dest);
427    ccprintf(ss, ", ");
428    printVecPredReg(ss, gp);
429    ccprintf(ss, ", ");
430    printVecReg(ss, op1, true);
431    return ss.str();
432}
433
434std::string
435SveOrdReducOp::generateDisassembly(Addr pc,
436                                const SymbolTable *symtab) const
437{
438    std::stringstream ss;
439    printMnemonic(ss, "", false);
440    printFloatReg(ss, dest);
441    ccprintf(ss, ", ");
442    printVecPredReg(ss, gp);
443    ccprintf(ss, ", ");
444    printFloatReg(ss, dest);
445    ccprintf(ss, ", ");
446    printVecReg(ss, op1, true);
447    return ss.str();
448}
449
450std::string
451SvePtrueOp::generateDisassembly(Addr pc,
452                                const SymbolTable *symtab) const
453{
454    std::stringstream ss;
455    printMnemonic(ss, "", false);
456    printVecPredReg(ss, dest);
457    if (imm != 0x1f) {
458        ccprintf(ss, ", ");
459        ss << sveDisasmPredCountImm(imm);
460    }
461    return ss.str();
462}
463
464std::string
465SveIntCmpOp::generateDisassembly(Addr pc,
466        const SymbolTable *symtab) const
467{
468    std::stringstream ss;
469    printMnemonic(ss, "", false);
470    printVecPredReg(ss, dest);
471    ccprintf(ss, ", ");
472    printVecPredReg(ss, gp);
473    ccprintf(ss, "/z, ");
474    printVecReg(ss, op1, true);
475    ccprintf(ss, ", ");
476    if (op2IsWide) {
477        printVecReg(ss, op2, true);
478    } else {
479        printVecReg(ss, op2, true);
480    }
481    return ss.str();
482}
483
484std::string
485SveIntCmpImmOp::generateDisassembly(Addr pc,
486        const SymbolTable *symtab) const
487{
488    std::stringstream ss;
489    printMnemonic(ss, "", false);
490    printVecPredReg(ss, dest);
491    ccprintf(ss, "/z, ");
492    printVecPredReg(ss, gp);
493    ccprintf(ss, ", ");
494    printVecReg(ss, op1, true);
495    ccprintf(ss, ", #");
496    ss << imm;
497    return ss.str();
498}
499
500std::string
501SveAdrOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
502{
503    std::stringstream ss;
504    printMnemonic(ss, "", false);
505    printVecReg(ss, dest, true);
506    ccprintf(ss, ", [");
507    printVecReg(ss, op1, true);
508    ccprintf(ss, ", ");
509    printVecReg(ss, op2, true);
510    if (offsetFormat == SveAdrOffsetUnpackedSigned) {
511        ccprintf(ss, ", sxtw");
512    } else if (offsetFormat == SveAdrOffsetUnpackedUnsigned) {
513        ccprintf(ss, ", uxtw");
514    } else if (mult != 1) {
515        ccprintf(ss, ", lsl");
516    }
517    if (mult != 1) {
518        ss << __builtin_ctz(mult);
519    }
520    ccprintf(ss, "]");
521    return ss.str();
522}
523
524std::string
525SveElemCountOp::generateDisassembly(Addr pc,
526        const SymbolTable *symtab) const
527{
528    static const char suffix[9] =
529        {'\0', 'b', 'h', '\0', 'w', '\0', '\0', '\0', 'd'};
530    std::stringstream ss;
531    ss << "  " << mnemonic << suffix[esize] << "   ";
532    if (dstIsVec) {
533        printVecReg(ss, dest, true);
534    } else {
535        if (dstIs32b) {
536            printIntReg(ss, dest, 32);
537        } else {
538            printIntReg(ss, dest, 64);
539        }
540    }
541    if (pattern != 0x1f) {
542        ccprintf(ss, ", ");
543        ss << sveDisasmPredCountImm(pattern);
544        if (imm != 1) {
545            ccprintf(ss, ", mul #");
546            ss << std::to_string(imm);
547        }
548    }
549    return ss.str();
550}
551
552std::string
553SvePartBrkOp::generateDisassembly(Addr pc,
554        const SymbolTable *symtab) const
555{
556    std::stringstream ss;
557    printMnemonic(ss, "", false);
558    printVecPredReg(ss, dest);
559    ccprintf(ss, ", ");
560    printVecPredReg(ss, gp);
561    ccprintf(ss, isMerging ? "/m, " : "/z, ");
562    printVecPredReg(ss, op1);
563    return ss.str();
564}
565
566std::string
567SvePartBrkPropOp::generateDisassembly(Addr pc,
568        const SymbolTable *symtab) const
569{
570    std::stringstream ss;
571    printMnemonic(ss, "", false);
572    printVecPredReg(ss, dest);
573    ccprintf(ss, ", ");
574    printVecPredReg(ss, gp);
575    ccprintf(ss, "/z, ");
576    printVecPredReg(ss, op1);
577    ccprintf(ss, ", ");
578    printVecPredReg(ss, op2);
579    return ss.str();
580}
581
582std::string
583SveSelectOp::generateDisassembly(Addr pc,
584        const SymbolTable *symtab) const
585{
586    std::stringstream ss;
587    printMnemonic(ss, "", false);
588    if (scalar)
589        printIntReg(ss, dest, scalar_width);
590    else if (simdFp)
591        printFloatReg(ss, dest);
592    else
593        printVecReg(ss, dest, true);
594    ccprintf(ss, ", ");
595    printVecPredReg(ss, gp);
596    if (conditional) {
597        ccprintf(ss, ", ");
598        if (scalar)
599            printIntReg(ss, dest, scalar_width);
600        else
601            printVecReg(ss, dest, true);
602    }
603    ccprintf(ss, ", ");
604    printVecReg(ss, op1, true);
605    return ss.str();
606}
607
608std::string
609SveUnaryPredPredOp::generateDisassembly(Addr pc,
610        const SymbolTable *symtab) const
611{
612    std::stringstream ss;
613    printMnemonic(ss, "", false);
614    printVecPredReg(ss, dest);
615    ccprintf(ss, ", ");
616    printVecPredReg(ss, gp);
617    ccprintf(ss, ", ");
618    printVecPredReg(ss, op1);
619    return ss.str();
620}
621
622std::string
623SveTblOp::generateDisassembly(Addr pc,
624        const SymbolTable *symtab) const
625{
626    std::stringstream ss;
627    printMnemonic(ss, "", false);
628    printVecReg(ss, dest, true);
629    ccprintf(ss, ", { ");
630    printVecReg(ss, op1, true);
631    ccprintf(ss, " }, ");
632    printVecReg(ss, op2, true);
633    return ss.str();
634}
635
636std::string
637SveUnpackOp::generateDisassembly(Addr pc,
638        const SymbolTable *symtab) const
639{
640    std::stringstream ss;
641    printMnemonic(ss, "", false);
642    printVecPredReg(ss, dest);
643    ccprintf(ss, ", ");
644    printVecPredReg(ss, op1);
645    return ss.str();
646}
647
648std::string
649SvePredTestOp::generateDisassembly(Addr pc,
650        const SymbolTable *symtab) const
651{
652    std::stringstream ss;
653    printMnemonic(ss, "", false);
654    printVecPredReg(ss, gp);
655    ccprintf(ss, ", ");
656    printVecPredReg(ss, op1);
657    return ss.str();
658}
659
660std::string
661SvePredUnaryWImplicitSrcOp::generateDisassembly(Addr pc,
662        const SymbolTable *symtab) const
663{
664    std::stringstream ss;
665    printMnemonic(ss, "", false);
666    printVecPredReg(ss, dest);
667    return ss.str();
668}
669
670std::string
671SvePredUnaryWImplicitSrcPredOp::generateDisassembly(Addr pc,
672        const SymbolTable *symtab) const
673{
674    std::stringstream ss;
675    printMnemonic(ss, "", false);
676    printVecPredReg(ss, dest);
677    ccprintf(ss, ", ");
678    printVecPredReg(ss, gp);
679    ccprintf(ss, "/z, ");
680    return ss.str();
681}
682
683std::string
684SvePredUnaryWImplicitDstOp::generateDisassembly(Addr pc,
685        const SymbolTable *symtab) const
686{
687    std::stringstream ss;
688    printMnemonic(ss, "", false);
689    printVecPredReg(ss, op1);
690    return ss.str();
691}
692
693std::string
694SveWImplicitSrcDstOp::generateDisassembly(Addr pc,
695        const SymbolTable *symtab) const
696{
697    std::stringstream ss;
698    printMnemonic(ss, "", false);
699    return ss.str();
700}
701
702std::string
703SveBinImmUnpredDestrOp::generateDisassembly(Addr pc,
704        const SymbolTable *symtab) const
705{
706    std::stringstream ss;
707    printMnemonic(ss, "", false);
708    printVecReg(ss, dest, true);
709    ccprintf(ss, ", ");
710    printVecReg(ss, dest, true);
711    ccprintf(ss, ", ");
712    printVecReg(ss, op1, true);
713    ccprintf(ss, ", #");
714    ss << imm;
715    return ss.str();
716}
717
718std::string
719SveBinImmIdxUnpredOp::generateDisassembly(Addr pc,
720        const SymbolTable *symtab) const
721{
722    std::stringstream ss;
723    printMnemonic(ss, "", false);
724    printVecReg(ss, dest, true);
725    ccprintf(ss, ", ");
726    printVecReg(ss, op1, true);
727    ccprintf(ss, "[");
728    ss << imm;
729    ccprintf(ss, "]");
730    return ss.str();
731}
732
733std::string
734SveUnarySca2VecUnpredOp::generateDisassembly(Addr pc,
735        const SymbolTable *symtab) const
736{
737    std::stringstream ss;
738    printMnemonic(ss, "", false);
739    printVecReg(ss, dest, true);
740    ccprintf(ss, ", ");
741    if (simdFp) {
742        printFloatReg(ss, op1);
743    } else {
744        printIntReg(ss, op1);
745    }
746    return ss.str();
747}
748
749std::string
750SveDotProdIdxOp::generateDisassembly(Addr pc,
751        const SymbolTable *symtab) const
752{
753    std::stringstream ss;
754    printMnemonic(ss, "", false);
755    printVecReg(ss, dest, true);
756    ccprintf(ss, ", ");
757    printVecReg(ss, op1, true);
758    ccprintf(ss, ", ");
759    printVecReg(ss, op2, true);
760    ccprintf(ss, "[");
761    ccprintf(ss, "%lu", imm);
762    ccprintf(ss, "]");
763    return ss.str();
764}
765
766std::string
767SveDotProdOp::generateDisassembly(Addr pc,
768        const SymbolTable *symtab) const
769{
770    std::stringstream ss;
771    printMnemonic(ss, "", false);
772    printVecReg(ss, dest, true);
773    ccprintf(ss, ", ");
774    printVecReg(ss, op1, true);
775    ccprintf(ss, ", ");
776    printVecReg(ss, op2, true);
777    return ss.str();
778}
779
780std::string
781SveComplexOp::generateDisassembly(Addr pc,
782        const SymbolTable *symtab) const
783{
784    std::stringstream ss;
785    printMnemonic(ss, "", false);
786    printVecPredReg(ss, dest);
787    ccprintf(ss, ", ");
788    printVecPredReg(ss, gp);
789    ccprintf(ss, "/m, ");
790    printVecPredReg(ss, op1);
791    ccprintf(ss, ", ");
792    printVecPredReg(ss, op2);
793    ccprintf(ss, ", #");
794    const char* rotstr[4] = {"0", "90", "180", "270"};
795    ccprintf(ss, rotstr[rot]);
796
797    return ss.str();
798}
799
800std::string
801SveComplexIdxOp::generateDisassembly(Addr pc,
802        const SymbolTable *symtab) const
803{
804    std::stringstream ss;
805    printMnemonic(ss, "", false);
806    printVecPredReg(ss, dest);
807    ccprintf(ss, ", ");
808    printVecPredReg(ss, op1);
809    ccprintf(ss, ", ");
810    printVecPredReg(ss, op2);
811    ccprintf(ss, "[");
812    ss << imm;
813    ccprintf(ss, "], #");
814    const char* rotstr[4] = {"0", "90", "180", "270"};
815    ccprintf(ss, rotstr[rot]);
816    return ss.str();
817}
818
819std::string
820sveDisasmPredCountImm(uint8_t imm)
821{
822    switch (imm) {
823      case 0x0:
824        return "POW2";
825      case 0x1:
826      case 0x2:
827      case 0x3:
828      case 0x4:
829      case 0x5:
830      case 0x6:
831      case 0x7:
832        return "VL" + std::to_string(imm);
833      case 0x8:
834      case 0x9:
835      case 0xa:
836      case 0xb:
837      case 0xc:
838      case 0xd:
839        return "VL" + std::to_string(1 << ((imm & 0x7) + 3));
840      case 0x1d:
841        return "MUL4";
842      case 0x1e:
843        return "MUL3";
844      case 0x1f:
845        return "ALL";
846      default:
847        return "#" + std::to_string(imm);
848    }
849}
850
851unsigned int
852sveDecodePredCount(uint8_t imm, unsigned int num_elems)
853{
854    assert(num_elems > 0);
855
856    switch (imm) {
857      case 0x0:
858        // POW2
859        return 1 << (31 - __builtin_clz((uint32_t) num_elems));
860      case 0x1:
861      case 0x2:
862      case 0x3:
863      case 0x4:
864      case 0x5:
865      case 0x6:
866      case 0x7:
867        // VL1, VL2, VL3, VL4, VL5, VL6, VL7
868        return (num_elems >= imm) ? imm : 0;
869      case 0x8:
870      case 0x9:
871      case 0xa:
872      case 0xb:
873      case 0xc:
874      case 0xd:
875        // VL8, VL16, VL32, VL64, VL128, VL256
876        {
877            unsigned int pcount = 1 << ((imm & 0x7) + 3);
878            return (num_elems >= pcount) ? pcount : 0;
879        }
880      case 0x1d:
881        // MUL4
882        return num_elems - (num_elems % 4);
883      case 0x1e:
884        // MUL3
885        return num_elems - (num_elems % 3);
886      case 0x1f:
887        // ALL
888        return num_elems;
889      default:
890        return 0;
891    }
892}
893
894uint64_t
895sveExpandFpImmAddSub(uint8_t imm, uint8_t size)
896{
897    static constexpr uint16_t fpOne16 = 0x3c00;
898    static constexpr uint16_t fpPointFive16 = 0x3800;
899    static constexpr uint32_t fpOne32 = 0x3f800000;
900    static constexpr uint32_t fpPointFive32 = 0x3f000000;
901    static constexpr uint64_t fpOne64 = 0x3ff0000000000000;
902    static constexpr uint64_t fpPointFive64 = 0x3fe0000000000000;
903
904    switch (size) {
905      case 0x1:
906        return imm ? fpOne16 : fpPointFive16;
907      case 0x2:
908        return imm ? fpOne32 : fpPointFive32;
909      case 0x3:
910        return imm ? fpOne64 : fpPointFive64;
911      default:
912        panic("Unsupported size");
913    }
914}
915
916uint64_t
917sveExpandFpImmMaxMin(uint8_t imm, uint8_t size)
918{
919    static constexpr uint16_t fpOne16 = 0x3c00;
920    static constexpr uint32_t fpOne32 = 0x3f800000;
921    static constexpr uint64_t fpOne64 = 0x3ff0000000000000;
922
923    switch (size) {
924      case 0x1:
925        return imm ? fpOne16 : 0x0;
926      case 0x2:
927        return imm ? fpOne32 : 0x0;
928      case 0x3:
929        return imm ? fpOne64 : 0x0;
930      default:
931        panic("Unsupported size");
932    }
933}
934
935uint64_t
936sveExpandFpImmMul(uint8_t imm, uint8_t size)
937{
938    static constexpr uint16_t fpTwo16 = 0x4000;
939    static constexpr uint16_t fpPointFive16 = 0x3800;
940    static constexpr uint32_t fpTwo32 = 0x40000000;
941    static constexpr uint32_t fpPointFive32 = 0x3f000000;
942    static constexpr uint64_t fpTwo64 = 0x4000000000000000;
943    static constexpr uint64_t fpPointFive64 = 0x3fe0000000000000;
944
945    switch (size) {
946      case 0x1:
947        return imm ? fpTwo16 : fpPointFive16;
948      case 0x2:
949        return imm ? fpTwo32 : fpPointFive32;
950      case 0x3:
951        return imm ? fpTwo64 : fpPointFive64;
952      default:
953        panic("Unsupported size");
954    }
955}
956
957}  // namespace ArmISA
958