sve_mem.isa revision 14106
1// Copyright (c) 2017-2018 ARM Limited
2// All rights reserved
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder.  You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Giacomo Gabrielli
37
38def template SveMemFillSpillOpDeclare {{
39    class %(class_name)s : public %(base_class)s
40    {
41      protected:
42        typedef uint8_t TPElem;
43        typedef uint8_t RegElemType;
44        typedef uint8_t MemElemType;
45
46      public:
47        %(class_name)s(ExtMachInst machInst,
48            IntRegIndex _dest, IntRegIndex _base, uint64_t _imm)
49            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
50                _dest, _base, _imm)
51        {
52            %(constructor)s;
53        }
54
55        Fault execute(ExecContext *, Trace::InstRecord *) const;
56        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
57        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
58
59        virtual void
60        annotateFault(ArmFault *fault) {
61            %(fa_code)s
62        }
63    };
64}};
65
66def template SveContigMemSSOpDeclare {{
67    %(tpl_header)s
68    class %(class_name)s : public %(base_class)s
69    {
70      protected:
71        typedef RegElemType TPElem;
72
73      public:
74        %(class_name)s(const char* mnem, ExtMachInst machInst,
75            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
76            IntRegIndex _offset)
77            : %(base_class)s(mnem, machInst, %(op_class)s,
78                _dest, _gp, _base, _offset)
79        {
80            %(constructor)s;
81        }
82
83        Fault execute(ExecContext *, Trace::InstRecord *) const;
84        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
85        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
86
87        virtual void
88        annotateFault(ArmFault *fault) {
89            %(fa_code)s
90        }
91    };
92}};
93
94def template SveContigMemSIOpDeclare {{
95    %(tpl_header)s
96    class %(class_name)s : public %(base_class)s
97    {
98      protected:
99        typedef RegElemType TPElem;
100
101      public:
102        %(class_name)s(const char* mnem, ExtMachInst machInst,
103            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
104            uint64_t _imm)
105            : %(base_class)s(mnem, machInst, %(op_class)s,
106                _dest, _gp, _base, _imm)
107        {
108            %(constructor)s;
109        }
110
111        Fault execute(ExecContext *, Trace::InstRecord *) const;
112        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
113        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
114
115        virtual void
116        annotateFault(ArmFault *fault) {
117            %(fa_code)s
118        }
119    };
120}};
121
122def template SveContigMemExecDeclare {{
123    template
124    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *,
125        Trace::InstRecord *) const;
126
127    template
128    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *,
129        Trace::InstRecord *) const;
130
131    template
132    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr,
133        ExecContext *, Trace::InstRecord *) const;
134}};
135
136def template SveContigLoadExecute {{
137    %(tpl_header)s
138    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
139        Trace::InstRecord *traceData) const
140    {
141        Addr EA;
142        Fault fault = NoFault;
143        bool aarch64 M5_VAR_USED = true;
144        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
145            xc->tcBase());
146
147        %(op_decl)s;
148        %(op_rd)s;
149        %(ea_code)s;
150
151        TheISA::VecRegContainer memData;
152        auto memDataView = memData.as<MemElemType>();
153
154        %(rden_code)s;
155
156        fault = xc->readMem(EA, memData.raw_ptr<uint8_t>(), memAccessSize,
157            this->memAccessFlags, rdEn);
158
159        %(fault_code)s;
160
161        if (fault == NoFault) {
162            %(memacc_code)s;
163            %(op_wb)s;
164        }
165
166        return fault;
167    }
168}};
169
170def template SveContigLoadInitiateAcc {{
171    %(tpl_header)s
172    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
173        Trace::InstRecord *traceData) const
174    {
175        Addr EA;
176        Fault fault = NoFault;
177        bool aarch64 M5_VAR_USED = true;
178        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
179            xc->tcBase());
180
181        %(op_src_decl)s;
182        %(op_rd)s;
183        %(ea_code)s;
184
185        %(rden_code)s;
186
187        fault = xc->initiateMemRead(EA, memAccessSize, this->memAccessFlags,
188            rdEn);
189
190        %(fault_code)s;
191
192        return fault;
193    }
194}};
195
196def template SveContigLoadCompleteAcc {{
197    %(tpl_header)s
198    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
199        ExecContext *xc, Trace::InstRecord *traceData) const
200    {
201        bool aarch64 M5_VAR_USED = true;
202        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
203            xc->tcBase());
204
205        %(op_decl)s;
206        %(op_rd)s;
207
208        TheISA::VecRegContainer memData;
209        auto memDataView = memData.as<MemElemType>();
210
211        if (xc->readMemAccPredicate()) {
212            memcpy(memData.raw_ptr<uint8_t>(), pkt->getPtr<uint8_t>(),
213                   pkt->getSize());
214        }
215
216        %(memacc_code)s;
217        %(op_wb)s;
218
219        return NoFault;
220    }
221}};
222
223def template SveContigStoreExecute {{
224    %(tpl_header)s
225    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
226        Trace::InstRecord *traceData) const
227    {
228        Addr EA;
229        Fault fault = NoFault;
230        bool aarch64 M5_VAR_USED = true;
231        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
232            xc->tcBase());
233
234        %(op_decl)s;
235        %(op_rd)s;
236        %(ea_code)s;
237
238        TheISA::VecRegContainer memData;
239        auto memDataView = memData.as<MemElemType>();
240
241        %(wren_code)s;
242
243        if (fault == NoFault) {
244            %(memacc_code)s;
245        }
246
247        if (fault == NoFault) {
248            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
249                this->memAccessFlags, NULL, wrEn);
250        }
251
252        if (fault == NoFault) {
253            %(op_wb)s;
254        }
255
256        return fault;
257    }
258}};
259
260def template SveContigStoreInitiateAcc {{
261    %(tpl_header)s
262    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
263        Trace::InstRecord *traceData) const
264    {
265        Addr EA;
266        Fault fault = NoFault;
267        bool aarch64 M5_VAR_USED = true;
268        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
269            xc->tcBase());
270
271        %(op_decl)s;
272        %(op_rd)s;
273        %(ea_code)s;
274
275        TheISA::VecRegContainer memData;
276        auto memDataView = memData.as<MemElemType>();
277
278        %(wren_code)s;
279
280        if (fault == NoFault) {
281            %(memacc_code)s;
282        }
283
284        if (fault == NoFault) {
285            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
286                this->memAccessFlags, NULL, wrEn);
287        }
288
289        return fault;
290    }
291}};
292
293def template SveContigStoreCompleteAcc {{
294    %(tpl_header)s
295    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
296        ExecContext *xc, Trace::InstRecord *traceData) const
297    {
298        return NoFault;
299    }
300}};
301
302def template SveLoadAndReplExecute {{
303    %(tpl_header)s
304    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
305        Trace::InstRecord *traceData) const
306    {
307        Addr EA;
308        Fault fault = NoFault;
309        bool aarch64 M5_VAR_USED = true;
310        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
311            xc->tcBase());
312
313        %(op_decl)s;
314        %(op_rd)s;
315        %(ea_code)s;
316
317        MemElemType memData;
318
319        if (fault == NoFault) {
320            fault = readMemAtomic(xc, traceData, EA, memData,
321                this->memAccessFlags);
322            %(memacc_code)s;
323        }
324
325        if (fault == NoFault) {
326            %(op_wb)s;
327        }
328
329        return fault;
330    }
331}};
332
333def template SveLoadAndReplInitiateAcc {{
334    %(tpl_header)s
335    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
336        Trace::InstRecord *traceData) const
337    {
338        Addr EA;
339        Fault fault = NoFault;
340        bool aarch64 M5_VAR_USED = true;
341
342        %(op_src_decl)s;
343        %(op_rd)s;
344
345        %(ea_code)s;
346
347        MemElemType memData;
348
349        if (fault == NoFault) {
350            fault = initiateMemRead(xc, traceData, EA, memData,
351                this->memAccessFlags);
352        }
353
354        return fault;
355    }
356}};
357
358def template SveLoadAndReplCompleteAcc {{
359    %(tpl_header)s
360    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
361        ExecContext *xc, Trace::InstRecord *traceData) const
362    {
363        Fault fault = NoFault;
364        bool aarch64 M5_VAR_USED = true;
365        unsigned eCount = ArmStaticInst::getCurSveVecLen<RegElemType>(
366            xc->tcBase());
367
368        %(op_decl)s;
369        %(op_rd)s;
370
371        MemElemType memData;
372        getMem(pkt, memData, traceData);
373
374        if (fault == NoFault) {
375            %(memacc_code)s;
376        }
377
378        if (fault == NoFault) {
379            %(op_wb)s;
380        }
381
382        return fault;
383    }
384}};
385
386def template SveIndexedMemVIMicroopDeclare {{
387    %(tpl_header)s
388    class %(class_name)s : public %(base_class)s
389    {
390      protected:
391        typedef RegElemType TPElem;
392
393        IntRegIndex dest;
394        IntRegIndex gp;
395        IntRegIndex base;
396        uint64_t imm;
397
398        int elemIndex;
399        int numElems;
400        bool firstFault;
401
402        unsigned memAccessFlags;
403
404      public:
405        %(class_name)s(const char* mnem, ExtMachInst machInst,
406            OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp,
407            IntRegIndex _base, uint64_t _imm, int _elemIndex, int _numElems,
408            bool _firstFault)
409            : %(base_class)s(mnem, machInst, %(op_class)s),
410              dest(_dest), gp(_gp), base(_base), imm(_imm),
411              elemIndex(_elemIndex), numElems(_numElems),
412              firstFault(_firstFault),
413              memAccessFlags(ArmISA::TLB::AllowUnaligned |
414                             ArmISA::TLB::MustBeOne)
415        {
416            %(constructor)s;
417            if (_opClass == MemReadOp && elemIndex == 0) {
418                // The first micro-op is responsible for pinning the
419                // destination and the fault status registers
420                assert(_numDestRegs == 2);
421               _destRegIdx[0].setNumPinnedWrites(numElems - 1);
422               _destRegIdx[1].setNumPinnedWrites(numElems - 1);
423            }
424        }
425
426        Fault execute(ExecContext *, Trace::InstRecord *) const;
427        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
428        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
429
430        virtual void
431        annotateFault(ArmFault *fault)
432        {
433            %(fa_code)s
434        }
435
436        std::string
437        generateDisassembly(Addr pc, const SymbolTable *symtab) const
438        {
439            // TODO: add suffix to transfer register
440            std::stringstream ss;
441            printMnemonic(ss, "", false);
442            ccprintf(ss, "{");
443            printVecReg(ss, dest, true);
444            ccprintf(ss, "}, ");
445            printVecPredReg(ss, gp);
446            if (_opClass == MemReadOp) {
447                ccprintf(ss, "/z");
448            }
449            ccprintf(ss, ", [");
450            printVecReg(ss, base, true);
451            if (imm != 0) {
452                ccprintf(ss, ", #%d", imm * sizeof(MemElemType));
453            }
454            ccprintf(ss, "] (uop elem %d tfer)", elemIndex);
455            return ss.str();
456        }
457    };
458}};
459
460def template SveIndexedMemSVMicroopDeclare {{
461    %(tpl_header)s
462    class %(class_name)s : public %(base_class)s
463    {
464      protected:
465        typedef RegElemType TPElem;
466
467        IntRegIndex dest;
468        IntRegIndex gp;
469        IntRegIndex base;
470        IntRegIndex offset;
471
472        bool offsetIs32;
473        bool offsetIsSigned;
474        bool offsetIsScaled;
475
476        int elemIndex;
477        int numElems;
478        bool firstFault;
479
480        unsigned memAccessFlags;
481
482      public:
483        %(class_name)s(const char* mnem, ExtMachInst machInst,
484            OpClass __opClass, IntRegIndex _dest, IntRegIndex _gp,
485            IntRegIndex _base, IntRegIndex _offset, bool _offsetIs32,
486            bool _offsetIsSigned, bool _offsetIsScaled, int _elemIndex,
487            int _numElems, bool _firstFault)
488            : %(base_class)s(mnem, machInst, %(op_class)s),
489              dest(_dest), gp(_gp), base(_base), offset(_offset),
490              offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned),
491              offsetIsScaled(_offsetIsScaled), elemIndex(_elemIndex),
492              numElems(_numElems), firstFault(_firstFault),
493              memAccessFlags(ArmISA::TLB::AllowUnaligned |
494                             ArmISA::TLB::MustBeOne)
495        {
496            %(constructor)s;
497            if (_opClass == MemReadOp && elemIndex == 0) {
498                // The first micro-op is responsible for pinning the
499                // destination and the fault status registers
500                assert(_numDestRegs == 2);
501               _destRegIdx[0].setNumPinnedWrites(numElems - 1);
502               _destRegIdx[1].setNumPinnedWrites(numElems - 1);
503            }
504        }
505
506        Fault execute(ExecContext *, Trace::InstRecord *) const;
507        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
508        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
509
510        virtual void
511        annotateFault(ArmFault *fault)
512        {
513            %(fa_code)s
514        }
515
516        std::string
517        generateDisassembly(Addr pc, const SymbolTable *symtab) const
518        {
519            // TODO: add suffix to transfer and base registers
520            std::stringstream ss;
521            printMnemonic(ss, "", false);
522            ccprintf(ss, "{");
523            printVecReg(ss, dest, true);
524            ccprintf(ss, "}, ");
525            printVecPredReg(ss, gp);
526            if (_opClass == MemReadOp) {
527                ccprintf(ss, "/z");
528            }
529            ccprintf(ss, ", [");
530            printIntReg(ss, base);
531            ccprintf(ss, ", ");
532            printVecReg(ss, offset, true);
533            ccprintf(ss, "] (uop elem %d tfer)", elemIndex);
534            return ss.str();
535        }
536    };
537}};
538
539def template SveGatherLoadMicroopExecute {{
540    %(tpl_header)s
541    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
542        Trace::InstRecord *traceData) const
543    {
544        Addr EA;
545        Fault fault = NoFault;
546        bool aarch64 M5_VAR_USED = true;
547
548        %(op_decl)s;
549        %(op_rd)s;
550        %(ea_code)s;
551
552        MemElemType memData = 0;
553
554        int index = elemIndex;
555        if (%(pred_check_code)s) {
556            fault = readMemAtomic(xc, traceData, EA, memData,
557                this->memAccessFlags);
558        }
559
560        if (fault == NoFault) {
561            %(fault_status_reset_code)s;
562            %(memacc_code)s;
563            %(op_wb)s;
564        } else {
565            %(fault_status_set_code)s;
566            if (firstFault) {
567               for (index = 0;
568                    index < numElems && !(%(pred_check_code)s);
569                    index++);
570
571               if (index < elemIndex) {
572                  fault = NoFault;
573                  memData = 0;
574                  %(memacc_code)s;
575                  %(op_wb)s;
576               }
577            }
578        }
579        return fault;
580    }
581}};
582
583def template SveGatherLoadMicroopInitiateAcc {{
584    %(tpl_header)s
585    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
586        Trace::InstRecord *traceData) const
587    {
588        Addr EA;
589        Fault fault = NoFault;
590        bool aarch64 M5_VAR_USED = true;
591
592        %(op_src_decl)s;
593        %(op_rd)s;
594        %(ea_code)s;
595
596        MemElemType memData;
597
598        int index = elemIndex;
599        if (%(pred_check_code)s) {
600            fault = initiateMemRead(xc, traceData, EA, memData,
601                this->memAccessFlags);
602            if (fault != NoFault) {
603                %(fault_status_set_code)s;
604                if (firstFault) {
605                    for (index = 0;
606                         index < numElems && !(%(pred_check_code)s);
607                         index++);
608                    if (index < elemIndex) {
609                        fault = NoFault;
610                        xc->setMemAccPredicate(false);
611                    }
612                }
613            } else {
614                %(fault_status_reset_code)s;
615            }
616        } else {
617            xc->setMemAccPredicate(false);
618            %(fault_status_reset_code)s;
619        }
620
621        return fault;
622    }
623}};
624
625def template SveGatherLoadMicroopCompleteAcc {{
626    %(tpl_header)s
627    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
628        ExecContext *xc, Trace::InstRecord *traceData) const
629    {
630        bool aarch64 M5_VAR_USED = true;
631
632        %(op_decl)s;
633        %(op_rd)s;
634
635        MemElemType memData = 0;
636        if (xc->readMemAccPredicate()) {
637            getMem(pkt, memData, traceData);
638        }
639
640        %(memacc_code)s;
641        %(op_wb)s;
642
643        return NoFault;
644    }
645}};
646
647def template SveScatterStoreMicroopExecute {{
648    %(tpl_header)s
649    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
650        Trace::InstRecord *traceData) const
651    {
652        Addr EA;
653        Fault fault = NoFault;
654        bool aarch64 M5_VAR_USED = true;
655
656        %(op_decl)s;
657        %(op_rd)s;
658        %(ea_code)s;
659
660        MemElemType memData;
661        %(memacc_code)s;
662
663        int index = elemIndex;
664        if (%(pred_check_code)s) {
665            fault = writeMemAtomic(xc, traceData, memData, EA,
666                                   this->memAccessFlags, NULL);
667        }
668
669        if (fault == NoFault) {
670            %(op_wb)s;
671        }
672
673        return fault;
674    }
675}};
676
677def template SveScatterStoreMicroopInitiateAcc {{
678    %(tpl_header)s
679    Fault %(class_name)s%(tpl_args)s::initiateAcc(ExecContext *xc,
680        Trace::InstRecord *traceData) const
681    {
682        Addr EA;
683        Fault fault = NoFault;
684        bool aarch64 M5_VAR_USED = true;
685
686        %(op_decl)s;
687        %(op_rd)s;
688        %(ea_code)s;
689
690        MemElemType memData;
691        %(memacc_code)s;
692
693        int index = elemIndex;
694        if (%(pred_check_code)s) {
695            fault = writeMemTiming(xc, traceData, memData, EA,
696                                   this->memAccessFlags, NULL);
697        } else {
698            xc->setPredicate(false);
699        }
700
701        return fault;
702    }
703}};
704
705def template SveScatterStoreMicroopCompleteAcc {{
706    %(tpl_header)s
707    Fault %(class_name)s%(tpl_args)s::completeAcc(PacketPtr pkt,
708        ExecContext *xc, Trace::InstRecord *traceData) const
709    {
710        return NoFault;
711    }
712}};
713
714def template SveFirstFaultWritebackMicroopDeclare {{
715    %(tpl_header)s
716    class SveFirstFaultWritebackMicroop : public MicroOp
717    {
718      protected:
719        typedef RegElemType TPElem;
720
721        int numElems;
722        StaticInst *macroOp;
723
724      public:
725        SveFirstFaultWritebackMicroop(const char* mnem, ExtMachInst machInst,
726            OpClass __opClass, int _numElems, StaticInst *_macroOp)
727            : MicroOp(mnem, machInst, __opClass),
728              numElems(_numElems), macroOp(_macroOp)
729        {
730            %(constructor)s;
731        }
732
733        Fault execute(ExecContext *, Trace::InstRecord *) const;
734
735        std::string
736        generateDisassembly(Addr pc, const SymbolTable *symtab) const
737        {
738            std::stringstream ss;
739            ccprintf(ss, "%s", macroOp->disassemble(pc, symtab));
740            ccprintf(ss, " (uop%d)", numElems);
741            return ss.str();
742        }
743    };
744}};
745
746def template SveFirstFaultWritebackMicroopExecute {{
747    %(tpl_header)s
748    Fault %(class_name)s%(tpl_args)s::execute(ExecContext *xc,
749        Trace::InstRecord *traceData) const
750    {
751        bool aarch64 M5_VAR_USED = true;
752
753        %(op_decl)s;
754        %(op_rd)s;
755
756        int  index, firstFaultIndex;
757        for (index = 0;
758             index < numElems && !%(fault_status_check_code)s;
759             index++);
760        firstFaultIndex = index;
761        for (index = 0; index < numElems; index++) {
762            if (index < firstFaultIndex) {
763                %(first_fault_forward_code)s;
764            } else {
765                %(first_fault_reset_code)s;
766            }
767        }
768        return NoFault;
769    }
770}};
771
772def template SveGatherLoadCpySrcVecMicroopDeclare {{
773    class SveGatherLoadCpySrcVecMicroop : public MicroOp
774    {
775      protected:
776        IntRegIndex op1;
777
778        StaticInst *macroOp;
779
780      public:
781        SveGatherLoadCpySrcVecMicroop(const char* mnem, ExtMachInst machInst,
782            IntRegIndex _op1, StaticInst *_macroOp)
783            : MicroOp(mnem, machInst, SimdAluOp), op1(_op1), macroOp(_macroOp)
784        {
785            %(constructor)s;
786        }
787
788        Fault execute(ExecContext *, Trace::InstRecord *) const;
789
790        std::string
791        generateDisassembly(Addr pc, const SymbolTable *symtab) const
792        {
793            std::stringstream ss;
794            ccprintf(ss, "%s", macroOp->disassemble(pc, symtab));
795            ccprintf(ss, " (uop src vec cpy)");
796            return ss.str();
797        }
798    };
799}};
800
801def template SveGatherLoadCpySrcVecMicroopExecute {{
802    Fault SveGatherLoadCpySrcVecMicroop::execute(ExecContext *xc,
803            Trace::InstRecord *traceData) const
804    {
805        Fault fault = NoFault;
806        %(op_decl)s;
807        %(op_rd)s;
808
809        %(code)s;
810        if (fault == NoFault)
811        {
812            %(op_wb)s;
813        }
814
815        return fault;
816    }
817}};
818
819def template SveStructMemSIMicroopDeclare {{
820    template<class _Element>
821    class %(class_name)s : public %(base_class)s
822    {
823      protected:
824        typedef _Element Element;
825        typedef _Element TPElem;
826
827        IntRegIndex dest;
828        IntRegIndex gp;
829        IntRegIndex base;
830        int64_t imm;
831
832        uint8_t numRegs;
833        int regIndex;
834
835        unsigned memAccessFlags;
836
837        bool baseIsSP;
838
839      public:
840        %(class_name)s(const char* mnem, ExtMachInst machInst,
841            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
842            int64_t _imm, uint8_t _numRegs, int _regIndex)
843            : %(base_class)s(mnem, machInst, %(op_class)s),
844              dest(_dest), gp(_gp), base(_base), imm(_imm),
845              numRegs(_numRegs), regIndex(_regIndex),
846              memAccessFlags(ArmISA::TLB::AllowUnaligned |
847                             ArmISA::TLB::MustBeOne)
848        {
849            %(constructor)s;
850            baseIsSP = isSP(_base);
851        }
852
853        Fault execute(ExecContext *, Trace::InstRecord *) const;
854        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
855        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
856
857        virtual void
858        annotateFault(ArmFault *fault)
859        {
860            %(fa_code)s
861        }
862
863        std::string
864        generateDisassembly(Addr pc, const SymbolTable *symtab) const
865        {
866            std::stringstream ss;
867            printMnemonic(ss, "", false);
868            ccprintf(ss, "{");
869            switch (dest) {
870                case INTRLVREG0:
871                    ccprintf(ss, "INTRLV0");
872                    break;
873                case INTRLVREG1:
874                    ccprintf(ss, "INTRLV1");
875                    break;
876                case INTRLVREG2:
877                    ccprintf(ss, "INTRLV2");
878                    break;
879                case INTRLVREG3:
880                    ccprintf(ss, "INTRLV3");
881                    break;
882                default:
883                    printVecReg(ss, dest, true);
884                    break;
885            }
886            ccprintf(ss, "}, ");
887            printVecPredReg(ss, gp);
888            if (_opClass == MemReadOp) {
889                ccprintf(ss, "/z");
890            }
891            ccprintf(ss, ", [");
892            printVecReg(ss, base, true);
893            if (imm != 0) {
894                ccprintf(ss, ", #%d", imm * sizeof(Element));
895            }
896            ccprintf(ss, "] (uop reg %d tfer)", regIndex);
897            return ss.str();
898        }
899    };
900}};
901
902def template SveStructMemExecDeclare {{
903    template
904    Fault %(class_name)s<%(targs)s>::execute(ExecContext *,
905        Trace::InstRecord *) const;
906
907    template
908    Fault %(class_name)s<%(targs)s>::initiateAcc(ExecContext *,
909        Trace::InstRecord *) const;
910
911    template
912    Fault %(class_name)s<%(targs)s>::completeAcc(PacketPtr,
913        ExecContext *, Trace::InstRecord *) const;
914}};
915
916def template SveStructLoadExecute {{
917    template <class Element>
918    Fault %(class_name)s<Element>::execute(ExecContext *xc,
919        Trace::InstRecord *traceData) const
920    {
921        Addr EA;
922        Fault fault = NoFault;
923        bool aarch64 M5_VAR_USED = true;
924        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
925            xc->tcBase());
926
927        %(op_decl)s;
928        %(op_rd)s;
929        %(ea_code)s;
930
931        TheISA::VecRegContainer memData;
932        auto memDataView = memData.as<Element>();
933
934        if (fault == NoFault) {
935            fault = xc->readMem(EA, memData.raw_ptr<uint8_t>(), memAccessSize,
936                this->memAccessFlags);
937            %(memacc_code)s;
938        }
939
940        if (fault == NoFault) {
941            %(op_wb)s;
942        }
943
944        return fault;
945    }
946}};
947
948def template SveStructLoadInitiateAcc {{
949    template <class Element>
950    Fault %(class_name)s<Element>::initiateAcc(ExecContext *xc,
951        Trace::InstRecord *traceData) const
952    {
953        Addr EA;
954        Fault fault = NoFault;
955        bool aarch64 M5_VAR_USED = true;
956        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
957            xc->tcBase());
958
959        %(op_src_decl)s;
960        %(op_rd)s;
961
962        %(ea_code)s;
963
964        if (fault == NoFault) {
965            fault = xc->initiateMemRead(EA, memAccessSize,
966                this->memAccessFlags);
967        }
968
969        return fault;
970    }
971}};
972
973def template SveStructLoadCompleteAcc {{
974    template <class Element>
975    Fault %(class_name)s<Element>::completeAcc(PacketPtr pkt,
976        ExecContext *xc, Trace::InstRecord *traceData) const
977    {
978        Fault fault = NoFault;
979        bool aarch64 M5_VAR_USED = true;
980        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
981            xc->tcBase());
982
983        %(op_decl)s;
984        %(op_rd)s;
985
986        TheISA::VecRegContainer memData;
987        auto memDataView = memData.as<Element>();
988
989        memcpy(memData.raw_ptr<uint8_t>(), pkt->getPtr<uint8_t>(),
990            pkt->getSize());
991
992        if (fault == NoFault) {
993            %(memacc_code)s;
994        }
995
996        if (fault == NoFault) {
997            %(op_wb)s;
998        }
999
1000        return fault;
1001    }
1002}};
1003
1004def template SveStructStoreExecute {{
1005    template <class Element>
1006    Fault %(class_name)s<Element>::execute(ExecContext *xc,
1007        Trace::InstRecord *traceData) const
1008    {
1009        Addr EA;
1010        Fault fault = NoFault;
1011        bool aarch64 M5_VAR_USED = true;
1012        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
1013            xc->tcBase());
1014
1015        %(op_decl)s;
1016        %(op_rd)s;
1017        %(ea_code)s;
1018
1019        TheISA::VecRegContainer memData;
1020        auto memDataView = memData.as<Element>();
1021
1022        %(wren_code)s;
1023
1024        if (fault == NoFault) {
1025            %(memacc_code)s;
1026        }
1027
1028        if (fault == NoFault) {
1029            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
1030                this->memAccessFlags, NULL, wrEn);
1031        }
1032
1033        if (fault == NoFault) {
1034            %(op_wb)s;
1035        }
1036
1037        return fault;
1038    }
1039}};
1040
1041def template SveStructStoreInitiateAcc {{
1042    template <class Element>
1043    Fault %(class_name)s<Element>::initiateAcc(ExecContext *xc,
1044        Trace::InstRecord *traceData) const
1045    {
1046        Addr EA;
1047        Fault fault = NoFault;
1048        bool aarch64 M5_VAR_USED = true;
1049        unsigned eCount = ArmStaticInst::getCurSveVecLen<Element>(
1050            xc->tcBase());
1051
1052        %(op_decl)s;
1053        %(op_rd)s;
1054        %(ea_code)s;
1055
1056        TheISA::VecRegContainer memData;
1057        auto memDataView = memData.as<Element>();
1058
1059        %(wren_code)s;
1060
1061        if (fault == NoFault) {
1062            %(memacc_code)s;
1063        }
1064
1065        if (fault == NoFault) {
1066            fault = xc->writeMem(memData.raw_ptr<uint8_t>(), memAccessSize, EA,
1067                this->memAccessFlags, NULL, wrEn);
1068        }
1069
1070        return fault;
1071    }
1072}};
1073
1074def template SveStructStoreCompleteAcc {{
1075    template <class Element>
1076    Fault %(class_name)s<Element>::completeAcc(PacketPtr pkt,
1077        ExecContext *xc, Trace::InstRecord *traceData) const
1078    {
1079        return NoFault;
1080    }
1081}};
1082
1083def template SveStructMemSSMicroopDeclare {{
1084    template <class _Element>
1085    class %(class_name)s : public %(base_class)s
1086    {
1087      protected:
1088        typedef _Element Element;
1089        typedef _Element TPElem;
1090
1091        IntRegIndex dest;
1092        IntRegIndex gp;
1093        IntRegIndex base;
1094        IntRegIndex offset;
1095
1096        uint8_t numRegs;
1097        int regIndex;
1098
1099        unsigned memAccessFlags;
1100
1101        bool baseIsSP;
1102
1103      public:
1104        %(class_name)s(const char* mnem, ExtMachInst machInst,
1105            IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
1106            IntRegIndex _offset, uint8_t _numRegs, int _regIndex)
1107            : %(base_class)s(mnem, machInst, %(op_class)s),
1108              dest(_dest), gp(_gp), base(_base), offset(_offset),
1109              numRegs(_numRegs), regIndex(_regIndex),
1110              memAccessFlags(ArmISA::TLB::AllowUnaligned |
1111                             ArmISA::TLB::MustBeOne)
1112        {
1113            %(constructor)s;
1114            baseIsSP = isSP(_base);
1115        }
1116
1117        Fault execute(ExecContext *, Trace::InstRecord *) const;
1118        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
1119        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
1120
1121        virtual void
1122        annotateFault(ArmFault *fault)
1123        {
1124            %(fa_code)s
1125        }
1126
1127        std::string
1128        generateDisassembly(Addr pc, const SymbolTable *symtab) const
1129        {
1130            std::stringstream ss;
1131            printMnemonic(ss, "", false);
1132            ccprintf(ss, "{");
1133            switch (dest) {
1134                case INTRLVREG0:
1135                    ccprintf(ss, "INTRLV0");
1136                    break;
1137                case INTRLVREG1:
1138                    ccprintf(ss, "INTRLV1");
1139                    break;
1140                case INTRLVREG2:
1141                    ccprintf(ss, "INTRLV2");
1142                    break;
1143                case INTRLVREG3:
1144                    ccprintf(ss, "INTRLV3");
1145                    break;
1146                default:
1147                    printVecReg(ss, dest, true);
1148                    break;
1149            }
1150            ccprintf(ss, "}, ");
1151            printVecPredReg(ss, gp);
1152            if (_opClass == MemReadOp) {
1153                ccprintf(ss, "/z");
1154            }
1155            ccprintf(ss, ", [");
1156            printIntReg(ss, base);
1157            ccprintf(ss, ", ");
1158            printVecReg(ss, offset, true);
1159            ccprintf(ss, "] (uop reg %d tfer)", regIndex);
1160            return ss.str();
1161        }
1162    };
1163}};
1164
1165def template SveIntrlvMicroopDeclare {{
1166    template <class _Element>
1167    class %(class_name)s: public %(base_class)s
1168    {
1169      protected:
1170        typedef _Element Element;
1171        typedef _Element TPElem;
1172        IntRegIndex dest;
1173        IntRegIndex op1;
1174        uint8_t numRegs;
1175        int regIndex;
1176
1177        StaticInst *macroOp;
1178
1179      public:
1180        %(class_name)s(const char* mnem, ExtMachInst machInst,
1181            IntRegIndex _dest, IntRegIndex _op1,
1182            uint8_t _numRegs, int _regIndex, StaticInst *_macroOp)
1183            : MicroOp(mnem, machInst, SimdAluOp),
1184            dest(_dest), op1(_op1), numRegs(_numRegs), regIndex(_regIndex),
1185            macroOp(_macroOp)
1186        {
1187            %(constructor)s;
1188        }
1189
1190        Fault execute(ExecContext *, Trace::InstRecord *) const;
1191
1192        std::string
1193        generateDisassembly(Addr pc, const SymbolTable *symtab) const
1194        {
1195            std::stringstream ss;
1196            ccprintf(ss, "%s", macroOp->disassemble(pc, symtab));
1197            ccprintf(ss, " (uop interleave)");
1198            return ss.str();
1199        }
1200    };
1201}};
1202
1203def template SveDeIntrlvMicroopDeclare {{
1204    template <class _Element>
1205    class %(class_name)s : public %(base_class)s
1206    {
1207      protected:
1208        typedef _Element Element;
1209        typedef _Element TPElem;
1210        IntRegIndex dest;
1211        uint8_t numRegs;
1212        int regIndex;
1213
1214        StaticInst *macroOp;
1215
1216      public:
1217        %(class_name)s(const char* mnem, ExtMachInst machInst,
1218            IntRegIndex _dest, uint8_t _numRegs, int _regIndex,
1219            StaticInst *_macroOp)
1220            : MicroOp(mnem, machInst, SimdAluOp),
1221            dest(_dest), numRegs(_numRegs), regIndex(_regIndex),
1222            macroOp(_macroOp)
1223        {
1224            %(constructor)s;
1225        }
1226
1227        Fault execute(ExecContext *, Trace::InstRecord *) const;
1228
1229        std::string
1230        generateDisassembly(Addr pc, const SymbolTable *symtab) const
1231        {
1232            std::stringstream ss;
1233            ccprintf(ss, "%s", macroOp->disassemble(pc, symtab));
1234            ccprintf(ss, " (uop deinterleave)");
1235            return ss.str();
1236        }
1237    };
1238}};
1239
1240def template SveIntrlvMicroopExecDeclare {{
1241    template
1242    Fault %(class_name)s<%(targs)s>::execute(
1243            ExecContext *, Trace::InstRecord *) const;
1244}};
1245
1246def template SveIntrlvMicroopExecute {{
1247    template <class Element>
1248    Fault %(class_name)s<Element>::execute(ExecContext *xc,
1249            Trace::InstRecord *traceData) const
1250    {
1251        Fault fault = NoFault;
1252        %(op_decl)s;
1253        %(op_rd)s;
1254
1255        %(code)s;
1256        if (fault == NoFault)
1257        {
1258            %(op_wb)s;
1259        }
1260
1261        return fault;
1262    }
1263}};
1264