1// -*- mode:c++ -*-
2
3// Copyright (c) 2010, 2012, 2014, 2016 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// Copyright (c) 2007-2008 The Florida State University
16// All rights reserved.
17//
18// Redistribution and use in source and binary forms, with or without
19// modification, are permitted provided that the following conditions are
20// met: redistributions of source code must retain the above copyright
21// notice, this list of conditions and the following disclaimer;
22// redistributions in binary form must reproduce the above copyright
23// notice, this list of conditions and the following disclaimer in the
24// documentation and/or other materials provided with the distribution;
25// neither the name of the copyright holders nor the names of its
26// contributors may be used to endorse or promote products derived from
27// this software without specific prior written permission.
28//
29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40//
41// Authors: Stephen Hines
42
43
44def template PanicExecute {{
45    Fault %(class_name)s::execute(ExecContext *xc,
46                                  Trace::InstRecord *traceData) const
47    {
48        panic("Execute function executed when it shouldn't be!\n");
49        return NoFault;
50    }
51}};
52
53def template PanicInitiateAcc {{
54    Fault %(class_name)s::initiateAcc(ExecContext *xc,
55                                      Trace::InstRecord *traceData) const
56    {
57        panic("InitiateAcc function executed when it shouldn't be!\n");
58        return NoFault;
59    }
60}};
61
62def template PanicCompleteAcc {{
63    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
64                                      Trace::InstRecord *traceData) const
65    {
66        panic("CompleteAcc function executed when it shouldn't be!\n");
67        return NoFault;
68    }
69}};
70
71
72def template SwapExecute {{
73    Fault %(class_name)s::execute(ExecContext *xc,
74                                  Trace::InstRecord *traceData) const
75    {
76        Addr EA;
77        Fault fault = NoFault;
78
79        %(op_decl)s;
80        uint64_t memData = 0;
81        %(op_rd)s;
82        %(ea_code)s;
83
84        if (%(predicate_test)s)
85        {
86            %(preacc_code)s;
87
88            if (fault == NoFault) {
89                fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
90                        &memData);
91            }
92
93            if (fault == NoFault) {
94                %(postacc_code)s;
95            }
96
97            if (fault == NoFault) {
98                %(op_wb)s;
99            }
100        } else {
101            xc->setPredicate(false);
102        }
103
104        return fault;
105    }
106}};
107
108def template SwapInitiateAcc {{
109    Fault %(class_name)s::initiateAcc(ExecContext *xc,
110                                      Trace::InstRecord *traceData) const
111    {
112        Addr EA;
113        Fault fault = NoFault;
114
115        %(op_decl)s;
116        uint64_t memData = 0;
117        %(op_rd)s;
118        %(ea_code)s;
119
120        if (%(predicate_test)s)
121        {
122            %(preacc_code)s;
123
124            if (fault == NoFault) {
125                fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
126                        &memData);
127            }
128        } else {
129            xc->setPredicate(false);
130        }
131
132        return fault;
133    }
134}};
135
136def template SwapCompleteAcc {{
137    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
138                                      Trace::InstRecord *traceData) const
139    {
140        Fault fault = NoFault;
141
142        %(op_decl)s;
143        %(op_rd)s;
144
145        if (%(predicate_test)s)
146        {
147            // ARM instructions will not have a pkt if the predicate is false
148            getMem(pkt, Mem, traceData);
149            uint64_t memData = Mem;
150
151            %(postacc_code)s;
152
153            if (fault == NoFault) {
154                %(op_wb)s;
155            }
156        }
157
158        return fault;
159    }
160}};
161
162def template LoadExecute {{
163    Fault %(class_name)s::execute(ExecContext *xc,
164                                  Trace::InstRecord *traceData) const
165    {
166        Addr EA;
167        Fault fault = NoFault;
168
169        %(op_decl)s;
170        %(op_rd)s;
171        %(ea_code)s;
172
173        if (%(predicate_test)s)
174        {
175            if (fault == NoFault) {
176                fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
177                %(memacc_code)s;
178            }
179
180            if (fault == NoFault) {
181                %(op_wb)s;
182            }
183        } else {
184            xc->setPredicate(false);
185        }
186
187        return fault;
188    }
189}};
190
191def template NeonLoadExecute {{
192    template <class Element>
193    Fault %(class_name)s<Element>::execute(
194            ExecContext *xc, Trace::InstRecord *traceData) const
195    {
196        Addr EA;
197        Fault fault = NoFault;
198
199        %(op_decl)s;
200        %(mem_decl)s;
201        %(op_rd)s;
202        %(ea_code)s;
203
204        MemUnion memUnion;
205        uint8_t *dataPtr = memUnion.bytes;
206
207        if (%(predicate_test)s)
208        {
209            if (fault == NoFault) {
210                fault = xc->readMem(EA, dataPtr, %(size)d, memAccessFlags);
211                %(memacc_code)s;
212            }
213
214            if (fault == NoFault) {
215                %(op_wb)s;
216            }
217        } else {
218            xc->setPredicate(false);
219        }
220
221        return fault;
222    }
223}};
224
225def template StoreExecute {{
226    Fault %(class_name)s::execute(ExecContext *xc,
227                                  Trace::InstRecord *traceData) const
228    {
229        Addr EA;
230        Fault fault = NoFault;
231
232        %(op_decl)s;
233        %(op_rd)s;
234        %(ea_code)s;
235
236        if (%(predicate_test)s)
237        {
238            if (fault == NoFault) {
239                %(memacc_code)s;
240            }
241
242            if (fault == NoFault) {
243                fault = writeMemAtomic(xc, traceData, Mem, EA,
244                        memAccessFlags, NULL);
245            }
246
247            if (fault == NoFault) {
248                %(op_wb)s;
249            }
250        } else {
251            xc->setPredicate(false);
252        }
253
254        return fault;
255    }
256}};
257
258def template NeonStoreExecute {{
259    template <class Element>
260    Fault %(class_name)s<Element>::execute(
261            ExecContext *xc, Trace::InstRecord *traceData) const
262    {
263        Addr EA;
264        Fault fault = NoFault;
265
266        %(op_decl)s;
267        %(mem_decl)s;
268        %(op_rd)s;
269        %(ea_code)s;
270
271        MemUnion memUnion;
272        uint8_t *dataPtr = memUnion.bytes;
273
274        if (%(predicate_test)s)
275        {
276            if (fault == NoFault) {
277                %(memacc_code)s;
278            }
279
280            if (fault == NoFault) {
281                fault = xc->writeMem(dataPtr, %(size)d, EA,
282                                     memAccessFlags, NULL);
283            }
284
285            if (fault == NoFault) {
286                %(op_wb)s;
287            }
288        } else {
289            xc->setPredicate(false);
290        }
291
292        return fault;
293    }
294}};
295
296def template StoreExExecute {{
297    Fault %(class_name)s::execute(ExecContext *xc,
298                                  Trace::InstRecord *traceData) const
299    {
300        Addr EA;
301        Fault fault = NoFault;
302
303        %(op_decl)s;
304        %(op_rd)s;
305        %(ea_code)s;
306
307        if (%(predicate_test)s)
308        {
309            if (fault == NoFault) {
310                %(memacc_code)s;
311            }
312
313            uint64_t writeResult;
314
315            if (fault == NoFault) {
316                fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
317                        &writeResult);
318            }
319
320            if (fault == NoFault) {
321                %(postacc_code)s;
322            }
323
324            if (fault == NoFault) {
325                %(op_wb)s;
326            }
327        } else {
328            xc->setPredicate(false);
329        }
330
331        return fault;
332    }
333}};
334
335def template StoreExInitiateAcc {{
336    Fault %(class_name)s::initiateAcc(ExecContext *xc,
337                                      Trace::InstRecord *traceData) const
338    {
339        Addr EA;
340        Fault fault = NoFault;
341
342        %(op_decl)s;
343        %(op_rd)s;
344        %(ea_code)s;
345
346        if (%(predicate_test)s)
347        {
348            if (fault == NoFault) {
349                %(memacc_code)s;
350            }
351
352            if (fault == NoFault) {
353                fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
354                        NULL);
355            }
356        } else {
357            xc->setPredicate(false);
358        }
359
360        return fault;
361    }
362}};
363
364def template StoreInitiateAcc {{
365    Fault %(class_name)s::initiateAcc(ExecContext *xc,
366                                      Trace::InstRecord *traceData) const
367    {
368        Addr EA;
369        Fault fault = NoFault;
370
371        %(op_decl)s;
372        %(op_rd)s;
373        %(ea_code)s;
374
375        if (%(predicate_test)s)
376        {
377            if (fault == NoFault) {
378                %(memacc_code)s;
379            }
380
381            if (fault == NoFault) {
382                fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
383                        NULL);
384            }
385        } else {
386            xc->setPredicate(false);
387        }
388
389        return fault;
390    }
391}};
392
393def template NeonStoreInitiateAcc {{
394    template <class Element>
395    Fault %(class_name)s<Element>::initiateAcc(
396            ExecContext *xc, Trace::InstRecord *traceData) const
397    {
398        Addr EA;
399        Fault fault = NoFault;
400
401        %(op_decl)s;
402        %(mem_decl)s;
403        %(op_rd)s;
404        %(ea_code)s;
405
406        if (%(predicate_test)s)
407        {
408            MemUnion memUnion;
409            if (fault == NoFault) {
410                %(memacc_code)s;
411            }
412
413            if (fault == NoFault) {
414                fault = xc->writeMem(memUnion.bytes, %(size)d, EA,
415                                     memAccessFlags, NULL);
416            }
417        } else {
418            xc->setPredicate(false);
419        }
420
421        return fault;
422    }
423}};
424
425def template LoadInitiateAcc {{
426    Fault %(class_name)s::initiateAcc(ExecContext *xc,
427                                      Trace::InstRecord *traceData) const
428    {
429        Addr EA;
430        Fault fault = NoFault;
431
432        %(op_src_decl)s;
433        %(op_rd)s;
434        %(ea_code)s;
435
436        if (%(predicate_test)s)
437        {
438            if (fault == NoFault) {
439                fault = initiateMemRead(xc, traceData, EA, Mem,
440                                        memAccessFlags);
441            }
442        } else {
443            xc->setPredicate(false);
444        }
445
446        return fault;
447    }
448}};
449
450def template NeonLoadInitiateAcc {{
451    template <class Element>
452    Fault %(class_name)s<Element>::initiateAcc(
453            ExecContext *xc, Trace::InstRecord *traceData) const
454    {
455        Addr EA;
456        Fault fault = NoFault;
457
458        %(op_decl)s;
459        %(mem_decl)s;
460        %(op_rd)s;
461        %(ea_code)s;
462
463        if (%(predicate_test)s)
464        {
465            if (fault == NoFault) {
466                fault = xc->initiateMemRead(EA, %(size)d, memAccessFlags);
467            }
468        } else {
469            xc->setPredicate(false);
470        }
471
472        return fault;
473    }
474}};
475
476def template LoadCompleteAcc {{
477    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
478                                      Trace::InstRecord *traceData) const
479    {
480        Fault fault = NoFault;
481
482        %(op_decl)s;
483        %(op_rd)s;
484
485        if (%(predicate_test)s)
486        {
487            // ARM instructions will not have a pkt if the predicate is false
488            getMem(pkt, Mem, traceData);
489
490            if (fault == NoFault) {
491                %(memacc_code)s;
492            }
493
494            if (fault == NoFault) {
495                %(op_wb)s;
496            }
497        }
498
499        return fault;
500    }
501}};
502
503def template NeonLoadCompleteAcc {{
504    template <class Element>
505    Fault %(class_name)s<Element>::completeAcc(
506            PacketPtr pkt, ExecContext *xc,
507            Trace::InstRecord *traceData) const
508    {
509        Fault fault = NoFault;
510
511        %(mem_decl)s;
512        %(op_decl)s;
513        %(op_rd)s;
514
515        if (%(predicate_test)s)
516        {
517            // ARM instructions will not have a pkt if the predicate is false
518            MemUnion &memUnion = *(MemUnion *)pkt->getPtr<uint8_t>();
519
520            if (fault == NoFault) {
521                %(memacc_code)s;
522            }
523
524            if (fault == NoFault) {
525                %(op_wb)s;
526            }
527        }
528
529        return fault;
530    }
531}};
532
533def template StoreCompleteAcc {{
534    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
535                                      Trace::InstRecord *traceData) const
536    {
537        return NoFault;
538    }
539}};
540
541def template NeonStoreCompleteAcc {{
542    template <class Element>
543    Fault %(class_name)s<Element>::completeAcc(
544            PacketPtr pkt, ExecContext *xc, Trace::InstRecord *traceData) const
545    {
546        return NoFault;
547    }
548}};
549
550def template StoreExCompleteAcc {{
551    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
552                                      Trace::InstRecord *traceData) const
553    {
554        Fault fault = NoFault;
555
556        %(op_decl)s;
557        %(op_rd)s;
558
559        if (%(predicate_test)s)
560        {
561            uint64_t writeResult = pkt->req->getExtraData();
562            %(postacc_code)s;
563
564            if (fault == NoFault) {
565                %(op_wb)s;
566            }
567        }
568
569        return fault;
570    }
571}};
572
573def template RfeDeclare {{
574    /**
575     * Static instruction class for "%(mnemonic)s".
576     */
577    class %(class_name)s : public %(base_class)s
578    {
579      public:
580
581        /// Constructor.
582        %(class_name)s(ExtMachInst machInst,
583                uint32_t _base, int _mode, bool _wb);
584
585        Fault execute(ExecContext *, Trace::InstRecord *) const override;
586        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
587        Fault completeAcc(PacketPtr, ExecContext *,
588                          Trace::InstRecord *) const override;
589    };
590}};
591
592def template SrsDeclare {{
593    /**
594     * Static instruction class for "%(mnemonic)s".
595     */
596    class %(class_name)s : public %(base_class)s
597    {
598      public:
599
600        /// Constructor.
601        %(class_name)s(ExtMachInst machInst,
602                uint32_t _regMode, int _mode, bool _wb);
603
604        Fault execute(ExecContext *, Trace::InstRecord *) const override;
605        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
606        Fault completeAcc(PacketPtr, ExecContext *,
607                          Trace::InstRecord *) const override;
608    };
609}};
610
611def template SwapDeclare {{
612    /**
613     * Static instruction class for "%(mnemonic)s".
614     */
615    class %(class_name)s : public %(base_class)s
616    {
617      public:
618
619        /// Constructor.
620        %(class_name)s(ExtMachInst machInst,
621                uint32_t _dest, uint32_t _op1, uint32_t _base);
622
623        Fault execute(ExecContext *, Trace::InstRecord *) const override;
624        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
625        Fault completeAcc(PacketPtr, ExecContext *,
626                          Trace::InstRecord *) const override;
627    };
628}};
629
630def template LoadStoreDImmDeclare {{
631    /**
632     * Static instruction class for "%(mnemonic)s".
633     */
634    class %(class_name)s : public %(base_class)s
635    {
636      public:
637
638        /// Constructor.
639        %(class_name)s(ExtMachInst machInst,
640                uint32_t _dest, uint32_t _dest2,
641                uint32_t _base, bool _add, int32_t _imm);
642
643        Fault execute(ExecContext *, Trace::InstRecord *) const override;
644        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
645        Fault completeAcc(PacketPtr, ExecContext *,
646                          Trace::InstRecord *) const override;
647    };
648}};
649
650def template StoreExDImmDeclare {{
651    /**
652     * Static instruction class for "%(mnemonic)s".
653     */
654    class %(class_name)s : public %(base_class)s
655    {
656      public:
657
658        /// Constructor.
659        %(class_name)s(ExtMachInst machInst,
660                uint32_t _result, uint32_t _dest, uint32_t _dest2,
661                uint32_t _base, bool _add, int32_t _imm);
662
663        Fault execute(ExecContext *, Trace::InstRecord *) const override;
664        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
665        Fault completeAcc(PacketPtr, ExecContext *,
666                          Trace::InstRecord *) const override;
667    };
668}};
669
670def template LoadStoreImmDeclare {{
671    /**
672     * Static instruction class for "%(mnemonic)s".
673     */
674    class %(class_name)s : public %(base_class)s
675    {
676      public:
677
678        /// Constructor.
679        %(class_name)s(ExtMachInst machInst,
680                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
681
682        Fault execute(ExecContext *, Trace::InstRecord *) const override;
683        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
684        Fault completeAcc(PacketPtr, ExecContext *,
685                          Trace::InstRecord *) const override;
686
687        void
688        annotateFault(ArmFault *fault) override
689        {
690            %(fa_code)s
691        }
692    };
693}};
694
695def template StoreExImmDeclare {{
696    /**
697     * Static instruction class for "%(mnemonic)s".
698     */
699    class %(class_name)s : public %(base_class)s
700    {
701      public:
702
703        /// Constructor.
704        %(class_name)s(ExtMachInst machInst,
705                uint32_t _result, uint32_t _dest, uint32_t _base,
706                bool _add, int32_t _imm);
707
708        Fault execute(ExecContext *, Trace::InstRecord *) const override;
709        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
710        Fault completeAcc(PacketPtr, ExecContext *,
711                          Trace::InstRecord *) const override;
712    };
713}};
714
715def template StoreDRegDeclare {{
716    /**
717     * Static instruction class for "%(mnemonic)s".
718     */
719    class %(class_name)s : public %(base_class)s
720    {
721      public:
722
723        /// Constructor.
724        %(class_name)s(ExtMachInst machInst,
725                uint32_t _dest, uint32_t _dest2,
726                uint32_t _base, bool _add,
727                int32_t _shiftAmt, uint32_t _shiftType,
728                uint32_t _index);
729
730        Fault execute(ExecContext *, Trace::InstRecord *) const override;
731        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
732        Fault completeAcc(PacketPtr, ExecContext *,
733                          Trace::InstRecord *) const override;
734    };
735}};
736
737def template StoreRegDeclare {{
738    /**
739     * Static instruction class for "%(mnemonic)s".
740     */
741    class %(class_name)s : public %(base_class)s
742    {
743      public:
744
745        /// Constructor.
746        %(class_name)s(ExtMachInst machInst,
747                uint32_t _dest, uint32_t _base, bool _add,
748                int32_t _shiftAmt, uint32_t _shiftType,
749                uint32_t _index);
750
751        Fault execute(ExecContext *, Trace::InstRecord *) const override;
752        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
753        Fault completeAcc(PacketPtr, ExecContext *,
754                          Trace::InstRecord *) const override;
755
756        void
757        annotateFault(ArmFault *fault) override
758        {
759            %(fa_code)s
760        }
761    };
762}};
763
764def template LoadDRegDeclare {{
765    /**
766     * Static instruction class for "%(mnemonic)s".
767     */
768    class %(class_name)s : public %(base_class)s
769    {
770      public:
771
772        /// Constructor.
773        %(class_name)s(ExtMachInst machInst,
774                uint32_t _dest, uint32_t _dest2,
775                uint32_t _base, bool _add,
776                int32_t _shiftAmt, uint32_t _shiftType,
777                uint32_t _index);
778
779        Fault execute(ExecContext *, Trace::InstRecord *) const override;
780        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
781        Fault completeAcc(PacketPtr, ExecContext *,
782                          Trace::InstRecord *) const override;
783    };
784}};
785
786def template LoadRegDeclare {{
787    /**
788     * Static instruction class for "%(mnemonic)s".
789     */
790    class %(class_name)s : public %(base_class)s
791    {
792      public:
793
794        /// Constructor.
795        %(class_name)s(ExtMachInst machInst,
796                uint32_t _dest, uint32_t _base, bool _add,
797                int32_t _shiftAmt, uint32_t _shiftType,
798                uint32_t _index);
799
800        Fault execute(ExecContext *, Trace::InstRecord *) const override;
801        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
802        Fault completeAcc(PacketPtr, ExecContext *,
803                          Trace::InstRecord *) const override;
804
805        void
806        annotateFault(ArmFault *fault) override
807        {
808            %(fa_code)s
809        }
810    };
811}};
812
813def template LoadImmDeclare {{
814    /**
815     * Static instruction class for "%(mnemonic)s".
816     */
817    class %(class_name)s : public %(base_class)s
818    {
819      public:
820
821        /// Constructor.
822        %(class_name)s(ExtMachInst machInst,
823                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
824
825        Fault execute(ExecContext *, Trace::InstRecord *) const override;
826        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
827        Fault completeAcc(PacketPtr, ExecContext *,
828                          Trace::InstRecord *) const override;
829
830        void
831        annotateFault(ArmFault *fault) override
832        {
833            %(fa_code)s
834        }
835    };
836}};
837
838def template RfeConstructor {{
839    %(class_name)s::%(class_name)s(ExtMachInst machInst,
840                                          uint32_t _base, int _mode, bool _wb)
841        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
842                         (IntRegIndex)_base, (AddrMode)_mode, _wb)
843    {
844        %(constructor)s;
845        if (!(condCode == COND_AL || condCode == COND_UC)) {
846            for (int x = 0; x < _numDestRegs; x++) {
847                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
848            }
849        }
850#if %(use_uops)d
851        uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
852        int uopIdx = 0;
853        uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
854        uops[uopIdx]->setDelayedCommit();
855#if %(use_wb)d
856        uops[++uopIdx] = new %(wb_decl)s;
857        uops[uopIdx]->setDelayedCommit();
858#endif
859#if %(use_pc)d
860        uops[++uopIdx] = new %(pc_decl)s;
861#endif
862        uops[0]->setFirstMicroop();
863        uops[uopIdx]->setLastMicroop();
864#endif
865    }
866}};
867
868def template SrsConstructor {{
869    %(class_name)s::%(class_name)s(ExtMachInst machInst,
870            uint32_t _regMode, int _mode, bool _wb)
871         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
872                 (OperatingMode)_regMode, (AddrMode)_mode, _wb)
873    {
874        %(constructor)s;
875        if (!(condCode == COND_AL || condCode == COND_UC)) {
876            for (int x = 0; x < _numDestRegs; x++) {
877                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
878            }
879        }
880#if %(use_uops)d
881        assert(numMicroops >= 2);
882        uops = new StaticInstPtr[numMicroops];
883        uops[0] = new %(acc_name)s(machInst, _regMode, _mode, _wb);
884        uops[0]->setDelayedCommit();
885        uops[0]->setFirstMicroop();
886        uops[1] = new %(wb_decl)s;
887        uops[1]->setLastMicroop();
888#endif
889    }
890}};
891
892def template SwapConstructor {{
893    %(class_name)s::%(class_name)s(ExtMachInst machInst,
894            uint32_t _dest, uint32_t _op1, uint32_t _base)
895         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
896                 (IntRegIndex)_dest, (IntRegIndex)_op1, (IntRegIndex)_base)
897    {
898        %(constructor)s;
899        if (!(condCode == COND_AL || condCode == COND_UC)) {
900            for (int x = 0; x < _numDestRegs; x++) {
901                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
902            }
903        }
904    }
905}};
906
907def template LoadStoreDImmConstructor {{
908    %(class_name)s::%(class_name)s(ExtMachInst machInst,
909            uint32_t _dest, uint32_t _dest2,
910            uint32_t _base, bool _add, int32_t _imm)
911         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
912                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
913                 (IntRegIndex)_base, _add, _imm)
914    {
915        %(constructor)s;
916        if (!(condCode == COND_AL || condCode == COND_UC)) {
917            for (int x = 0; x < _numDestRegs; x++) {
918                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
919            }
920        }
921#if %(use_uops)d
922        assert(numMicroops >= 2);
923        uops = new StaticInstPtr[numMicroops];
924        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add, _imm);
925        uops[0]->setFirstMicroop();
926        uops[0]->setDelayedCommit();
927        uops[1] = new %(wb_decl)s;
928        uops[1]->setLastMicroop();
929#endif
930    }
931}};
932
933def template StoreExDImmConstructor {{
934    %(class_name)s::%(class_name)s(ExtMachInst machInst,
935            uint32_t _result, uint32_t _dest, uint32_t _dest2,
936            uint32_t _base, bool _add, int32_t _imm)
937         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
938                 (IntRegIndex)_result,
939                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
940                 (IntRegIndex)_base, _add, _imm)
941    {
942        %(constructor)s;
943        if (!(condCode == COND_AL || condCode == COND_UC)) {
944            for (int x = 0; x < _numDestRegs; x++) {
945                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
946            }
947        }
948#if %(use_uops)d
949        assert(numMicroops >= 2);
950        uops = new StaticInstPtr[numMicroops];
951        uops[0] = new %(acc_name)s(machInst, _result, _dest, _dest2,
952                                   _base, _add, _imm);
953        uops[0]->setDelayedCommit();
954        uops[0]->setFirstMicroop();
955        uops[1] = new %(wb_decl)s;
956        uops[1]->setLastMicroop();
957#endif
958    }
959}};
960
961def template LoadStoreImmConstructor {{
962    %(class_name)s::%(class_name)s(ExtMachInst machInst,
963            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
964         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
965                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
966    {
967        %(constructor)s;
968        if (!(condCode == COND_AL || condCode == COND_UC)) {
969            for (int x = 0; x < _numDestRegs; x++) {
970                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
971            }
972        }
973#if %(use_uops)d
974        assert(numMicroops >= 2);
975        uops = new StaticInstPtr[numMicroops];
976        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
977        uops[0]->setDelayedCommit();
978        uops[0]->setFirstMicroop();
979        uops[1] = new %(wb_decl)s;
980        uops[1]->setLastMicroop();
981#endif
982    }
983}};
984
985def template StoreExImmConstructor {{
986    %(class_name)s::%(class_name)s(ExtMachInst machInst,
987            uint32_t _result, uint32_t _dest, uint32_t _base,
988            bool _add, int32_t _imm)
989         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
990                 (IntRegIndex)_result, (IntRegIndex)_dest,
991                 (IntRegIndex)_base, _add, _imm)
992    {
993        %(constructor)s;
994        if (!(condCode == COND_AL || condCode == COND_UC)) {
995            for (int x = 0; x < _numDestRegs; x++) {
996                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
997            }
998        }
999#if %(use_uops)d
1000        assert(numMicroops >= 2);
1001        uops = new StaticInstPtr[numMicroops];
1002        uops[0] = new %(acc_name)s(machInst, _result, _dest,
1003                                   _base, _add, _imm);
1004        uops[0]->setDelayedCommit();
1005        uops[0]->setFirstMicroop();
1006        uops[1] = new %(wb_decl)s;
1007        uops[1]->setLastMicroop();
1008#endif
1009    }
1010}};
1011
1012def template StoreDRegConstructor {{
1013    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1014            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1015            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1016         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1017                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1018                 (IntRegIndex)_base, _add,
1019                 _shiftAmt, (ArmShiftType)_shiftType,
1020                 (IntRegIndex)_index)
1021    {
1022        %(constructor)s;
1023        if (!(condCode == COND_AL || condCode == COND_UC)) {
1024            for (int x = 0; x < _numDestRegs; x++) {
1025                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1026            }
1027        }
1028#if %(use_uops)d
1029        assert(numMicroops >= 2);
1030        uops = new StaticInstPtr[numMicroops];
1031        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1032                                   _shiftAmt, _shiftType, _index);
1033        uops[0]->setDelayedCommit();
1034        uops[0]->setFirstMicroop();
1035        uops[1] = new %(wb_decl)s;
1036        uops[1]->setLastMicroop();
1037#endif
1038    }
1039}};
1040
1041def template StoreRegConstructor {{
1042    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1043            uint32_t _dest, uint32_t _base, bool _add,
1044            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1045         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1046                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1047                 _shiftAmt, (ArmShiftType)_shiftType,
1048                 (IntRegIndex)_index)
1049    {
1050        %(constructor)s;
1051        if (!(condCode == COND_AL || condCode == COND_UC)) {
1052            for (int x = 0; x < _numDestRegs; x++) {
1053                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1054            }
1055        }
1056#if %(use_uops)d
1057        assert(numMicroops >= 2);
1058        uops = new StaticInstPtr[numMicroops];
1059        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1060                                   _shiftAmt, _shiftType, _index);
1061        uops[0]->setDelayedCommit();
1062        uops[0]->setFirstMicroop();
1063        uops[1] = new %(wb_decl)s;
1064        uops[1]->setLastMicroop();
1065#endif
1066    }
1067}};
1068
1069def template LoadDRegConstructor {{
1070    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1071            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1072            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1073         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1074                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1075                 (IntRegIndex)_base, _add,
1076                 _shiftAmt, (ArmShiftType)_shiftType,
1077                 (IntRegIndex)_index)
1078    {
1079        %(constructor)s;
1080        if (!(condCode == COND_AL || condCode == COND_UC)) {
1081            for (int x = 0; x < _numDestRegs; x++) {
1082                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1083            }
1084        }
1085#if %(use_uops)d
1086        assert(numMicroops >= 2);
1087        uops = new StaticInstPtr[numMicroops];
1088        if ((_dest == _index) || (_dest2 == _index)) {
1089            IntRegIndex wbIndexReg = INTREG_UREG0;
1090            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1091            uops[0]->setDelayedCommit();
1092            uops[0]->setFirstMicroop();
1093            uops[1] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1094                                       _shiftAmt, _shiftType, _index);
1095            uops[1]->setDelayedCommit();
1096            uops[2] = new %(wb_decl)s;
1097            uops[2]->setLastMicroop();
1098        } else {
1099            IntRegIndex wbIndexReg = index;
1100            uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1101                                       _shiftAmt, _shiftType, _index);
1102            uops[0]->setDelayedCommit();
1103            uops[0]->setFirstMicroop();
1104            uops[1] = new %(wb_decl)s;
1105            uops[1]->setLastMicroop();
1106        }
1107#endif
1108    }
1109}};
1110
1111def template LoadRegConstructor {{
1112    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1113            uint32_t _dest, uint32_t _base, bool _add,
1114            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1115         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1116                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1117                 _shiftAmt, (ArmShiftType)_shiftType,
1118                 (IntRegIndex)_index)
1119    {
1120        %(constructor)s;
1121        bool conditional M5_VAR_USED = false;
1122        if (!(condCode == COND_AL || condCode == COND_UC)) {
1123            conditional = true;
1124            for (int x = 0; x < _numDestRegs; x++) {
1125                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1126            }
1127        }
1128#if %(use_uops)d
1129        assert(numMicroops >= 2);
1130        uops = new StaticInstPtr[numMicroops];
1131        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1132            IntRegIndex wbIndexReg = index;
1133            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1134                                       _shiftAmt, _shiftType, _index);
1135            uops[0]->setDelayedCommit();
1136            uops[0]->setFirstMicroop();
1137            uops[1] = new %(wb_decl)s;
1138            uops[1]->setDelayedCommit();
1139            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1140            uops[2]->setFlag(StaticInst::IsControl);
1141            uops[2]->setFlag(StaticInst::IsIndirectControl);
1142            if (conditional)
1143                uops[2]->setFlag(StaticInst::IsCondControl);
1144            else
1145                uops[2]->setFlag(StaticInst::IsUncondControl);
1146            uops[2]->setLastMicroop();
1147        } else if(_dest == _index) {
1148            IntRegIndex wbIndexReg = INTREG_UREG0;
1149            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1150            uops[0]->setDelayedCommit();
1151            uops[0]->setFirstMicroop();
1152            uops[1] = new %(acc_name)s(machInst, _dest, _base, _add,
1153                                      _shiftAmt, _shiftType, _index);
1154            uops[1]->setDelayedCommit();
1155            uops[2] = new %(wb_decl)s;
1156            uops[2]->setLastMicroop();
1157        } else {
1158            IntRegIndex wbIndexReg = index;
1159            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1160                                      _shiftAmt, _shiftType, _index);
1161            uops[0]->setDelayedCommit();
1162            uops[0]->setFirstMicroop();
1163            uops[1] = new %(wb_decl)s;
1164            uops[1]->setLastMicroop();
1165
1166        }
1167#else
1168        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1169            flags[IsControl] = true;
1170            flags[IsIndirectControl] = true;
1171            if (conditional)
1172                flags[IsCondControl] = true;
1173            else
1174                flags[IsUncondControl] = true;
1175        }
1176#endif
1177    }
1178}};
1179
1180def template LoadImmConstructor {{
1181    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1182            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
1183         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1184                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
1185    {
1186        %(constructor)s;
1187        bool conditional M5_VAR_USED = false;
1188        if (!(condCode == COND_AL || condCode == COND_UC)) {
1189            conditional = true;
1190            for (int x = 0; x < _numDestRegs; x++) {
1191                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1192            }
1193        }
1194#if %(use_uops)d
1195        assert(numMicroops >= 2);
1196        uops = new StaticInstPtr[numMicroops];
1197        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1198            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1199                                   _imm);
1200            uops[0]->setDelayedCommit();
1201            uops[0]->setFirstMicroop();
1202            uops[1] = new %(wb_decl)s;
1203            uops[1]->setDelayedCommit();
1204            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1205            uops[2]->setFlag(StaticInst::IsControl);
1206            uops[2]->setFlag(StaticInst::IsIndirectControl);
1207            /* Also set flags on the macroop so that pre-microop decomposition
1208                branch prediction can work */
1209            setFlag(StaticInst::IsControl);
1210            setFlag(StaticInst::IsIndirectControl);
1211            if (conditional) {
1212                uops[2]->setFlag(StaticInst::IsCondControl);
1213                setFlag(StaticInst::IsCondControl);
1214            } else {
1215                uops[2]->setFlag(StaticInst::IsUncondControl);
1216                setFlag(StaticInst::IsUncondControl);
1217            }
1218            if (_base == INTREG_SP && _add && _imm == 4 && %(is_ras_pop)s) {
1219                uops[2]->setFlag(StaticInst::IsReturn);
1220                setFlag(StaticInst::IsReturn);
1221            }
1222            uops[2]->setLastMicroop();
1223        } else {
1224            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
1225            uops[0]->setDelayedCommit();
1226            uops[0]->setFirstMicroop();
1227            uops[1] = new %(wb_decl)s;
1228            uops[1]->setLastMicroop();
1229        }
1230#else
1231        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1232            flags[IsControl] = true;
1233            flags[IsIndirectControl] = true;
1234            if (conditional)
1235                flags[IsCondControl] = true;
1236            else
1237                flags[IsUncondControl] = true;
1238        }
1239#endif
1240    }
1241}};
1242
1243