mem.isa revision 12234:78ece221f9f5
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        %(BasicExecDeclare)s
586
587        %(InitiateAccDeclare)s
588
589        %(CompleteAccDeclare)s
590    };
591}};
592
593def template SrsDeclare {{
594    /**
595     * Static instruction class for "%(mnemonic)s".
596     */
597    class %(class_name)s : public %(base_class)s
598    {
599      public:
600
601        /// Constructor.
602        %(class_name)s(ExtMachInst machInst,
603                uint32_t _regMode, int _mode, bool _wb);
604
605        %(BasicExecDeclare)s
606
607        %(InitiateAccDeclare)s
608
609        %(CompleteAccDeclare)s
610    };
611}};
612
613def template SwapDeclare {{
614    /**
615     * Static instruction class for "%(mnemonic)s".
616     */
617    class %(class_name)s : public %(base_class)s
618    {
619      public:
620
621        /// Constructor.
622        %(class_name)s(ExtMachInst machInst,
623                uint32_t _dest, uint32_t _op1, uint32_t _base);
624
625        %(BasicExecDeclare)s
626
627        %(InitiateAccDeclare)s
628
629        %(CompleteAccDeclare)s
630    };
631}};
632
633def template LoadStoreDImmDeclare {{
634    /**
635     * Static instruction class for "%(mnemonic)s".
636     */
637    class %(class_name)s : public %(base_class)s
638    {
639      public:
640
641        /// Constructor.
642        %(class_name)s(ExtMachInst machInst,
643                uint32_t _dest, uint32_t _dest2,
644                uint32_t _base, bool _add, int32_t _imm);
645
646        %(BasicExecDeclare)s
647
648        %(InitiateAccDeclare)s
649
650        %(CompleteAccDeclare)s
651    };
652}};
653
654def template StoreExDImmDeclare {{
655    /**
656     * Static instruction class for "%(mnemonic)s".
657     */
658    class %(class_name)s : public %(base_class)s
659    {
660      public:
661
662        /// Constructor.
663        %(class_name)s(ExtMachInst machInst,
664                uint32_t _result, uint32_t _dest, uint32_t _dest2,
665                uint32_t _base, bool _add, int32_t _imm);
666
667        %(BasicExecDeclare)s
668
669        %(InitiateAccDeclare)s
670
671        %(CompleteAccDeclare)s
672    };
673}};
674
675def template LoadStoreImmDeclare {{
676    /**
677     * Static instruction class for "%(mnemonic)s".
678     */
679    class %(class_name)s : public %(base_class)s
680    {
681      public:
682
683        /// Constructor.
684        %(class_name)s(ExtMachInst machInst,
685                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
686
687        %(BasicExecDeclare)s
688
689        %(InitiateAccDeclare)s
690
691        %(CompleteAccDeclare)s
692
693        virtual void
694        annotateFault(ArmFault *fault) {
695            %(fa_code)s
696        }
697    };
698}};
699
700def template StoreExImmDeclare {{
701    /**
702     * Static instruction class for "%(mnemonic)s".
703     */
704    class %(class_name)s : public %(base_class)s
705    {
706      public:
707
708        /// Constructor.
709        %(class_name)s(ExtMachInst machInst,
710                uint32_t _result, uint32_t _dest, uint32_t _base,
711                bool _add, int32_t _imm);
712
713        %(BasicExecDeclare)s
714
715        %(InitiateAccDeclare)s
716
717        %(CompleteAccDeclare)s
718    };
719}};
720
721def template StoreDRegDeclare {{
722    /**
723     * Static instruction class for "%(mnemonic)s".
724     */
725    class %(class_name)s : public %(base_class)s
726    {
727      public:
728
729        /// Constructor.
730        %(class_name)s(ExtMachInst machInst,
731                uint32_t _dest, uint32_t _dest2,
732                uint32_t _base, bool _add,
733                int32_t _shiftAmt, uint32_t _shiftType,
734                uint32_t _index);
735
736        %(BasicExecDeclare)s
737
738        %(InitiateAccDeclare)s
739
740        %(CompleteAccDeclare)s
741    };
742}};
743
744def template StoreRegDeclare {{
745    /**
746     * Static instruction class for "%(mnemonic)s".
747     */
748    class %(class_name)s : public %(base_class)s
749    {
750      public:
751
752        /// Constructor.
753        %(class_name)s(ExtMachInst machInst,
754                uint32_t _dest, uint32_t _base, bool _add,
755                int32_t _shiftAmt, uint32_t _shiftType,
756                uint32_t _index);
757
758        %(BasicExecDeclare)s
759
760        %(InitiateAccDeclare)s
761
762        %(CompleteAccDeclare)s
763
764        virtual void
765        annotateFault(ArmFault *fault) {
766            %(fa_code)s
767        }
768    };
769}};
770
771def template LoadDRegDeclare {{
772    /**
773     * Static instruction class for "%(mnemonic)s".
774     */
775    class %(class_name)s : public %(base_class)s
776    {
777      public:
778
779        /// Constructor.
780        %(class_name)s(ExtMachInst machInst,
781                uint32_t _dest, uint32_t _dest2,
782                uint32_t _base, bool _add,
783                int32_t _shiftAmt, uint32_t _shiftType,
784                uint32_t _index);
785
786        %(BasicExecDeclare)s
787
788        %(InitiateAccDeclare)s
789
790        %(CompleteAccDeclare)s
791    };
792}};
793
794def template LoadRegDeclare {{
795    /**
796     * Static instruction class for "%(mnemonic)s".
797     */
798    class %(class_name)s : public %(base_class)s
799    {
800      public:
801
802        /// Constructor.
803        %(class_name)s(ExtMachInst machInst,
804                uint32_t _dest, uint32_t _base, bool _add,
805                int32_t _shiftAmt, uint32_t _shiftType,
806                uint32_t _index);
807
808        %(BasicExecDeclare)s
809
810        %(InitiateAccDeclare)s
811
812        %(CompleteAccDeclare)s
813
814        virtual void
815        annotateFault(ArmFault *fault) {
816            %(fa_code)s
817        }
818    };
819}};
820
821def template LoadImmDeclare {{
822    /**
823     * Static instruction class for "%(mnemonic)s".
824     */
825    class %(class_name)s : public %(base_class)s
826    {
827      public:
828
829        /// Constructor.
830        %(class_name)s(ExtMachInst machInst,
831                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
832
833        %(BasicExecDeclare)s
834
835        %(InitiateAccDeclare)s
836
837        %(CompleteAccDeclare)s
838
839        virtual void
840        annotateFault(ArmFault *fault) {
841            %(fa_code)s
842        }
843    };
844}};
845
846def template InitiateAccDeclare {{
847    Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
848}};
849
850def template CompleteAccDeclare {{
851    Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
852}};
853
854def template RfeConstructor {{
855    %(class_name)s::%(class_name)s(ExtMachInst machInst,
856                                          uint32_t _base, int _mode, bool _wb)
857        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
858                         (IntRegIndex)_base, (AddrMode)_mode, _wb)
859    {
860        %(constructor)s;
861        if (!(condCode == COND_AL || condCode == COND_UC)) {
862            for (int x = 0; x < _numDestRegs; x++) {
863                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
864            }
865        }
866#if %(use_uops)d
867        uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
868        int uopIdx = 0;
869        uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
870        uops[uopIdx]->setDelayedCommit();
871#if %(use_wb)d
872        uops[++uopIdx] = new %(wb_decl)s;
873        uops[uopIdx]->setDelayedCommit();
874#endif
875#if %(use_pc)d
876        uops[++uopIdx] = new %(pc_decl)s;
877#endif
878        uops[0]->setFirstMicroop();
879        uops[uopIdx]->setLastMicroop();
880#endif
881    }
882}};
883
884def template SrsConstructor {{
885    %(class_name)s::%(class_name)s(ExtMachInst machInst,
886            uint32_t _regMode, int _mode, bool _wb)
887         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
888                 (OperatingMode)_regMode, (AddrMode)_mode, _wb)
889    {
890        %(constructor)s;
891        if (!(condCode == COND_AL || condCode == COND_UC)) {
892            for (int x = 0; x < _numDestRegs; x++) {
893                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
894            }
895        }
896#if %(use_uops)d
897        assert(numMicroops >= 2);
898        uops = new StaticInstPtr[numMicroops];
899        uops[0] = new %(acc_name)s(machInst, _regMode, _mode, _wb);
900        uops[0]->setDelayedCommit();
901        uops[0]->setFirstMicroop();
902        uops[1] = new %(wb_decl)s;
903        uops[1]->setLastMicroop();
904#endif
905    }
906}};
907
908def template SwapConstructor {{
909    %(class_name)s::%(class_name)s(ExtMachInst machInst,
910            uint32_t _dest, uint32_t _op1, uint32_t _base)
911         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
912                 (IntRegIndex)_dest, (IntRegIndex)_op1, (IntRegIndex)_base)
913    {
914        %(constructor)s;
915        if (!(condCode == COND_AL || condCode == COND_UC)) {
916            for (int x = 0; x < _numDestRegs; x++) {
917                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
918            }
919        }
920    }
921}};
922
923def template LoadStoreDImmConstructor {{
924    %(class_name)s::%(class_name)s(ExtMachInst machInst,
925            uint32_t _dest, uint32_t _dest2,
926            uint32_t _base, bool _add, int32_t _imm)
927         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
928                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
929                 (IntRegIndex)_base, _add, _imm)
930    {
931        %(constructor)s;
932        if (!(condCode == COND_AL || condCode == COND_UC)) {
933            for (int x = 0; x < _numDestRegs; x++) {
934                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
935            }
936        }
937#if %(use_uops)d
938        assert(numMicroops >= 2);
939        uops = new StaticInstPtr[numMicroops];
940        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add, _imm);
941        uops[0]->setFirstMicroop();
942        uops[0]->setDelayedCommit();
943        uops[1] = new %(wb_decl)s;
944        uops[1]->setLastMicroop();
945#endif
946    }
947}};
948
949def template StoreExDImmConstructor {{
950    %(class_name)s::%(class_name)s(ExtMachInst machInst,
951            uint32_t _result, uint32_t _dest, uint32_t _dest2,
952            uint32_t _base, bool _add, int32_t _imm)
953         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
954                 (IntRegIndex)_result,
955                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
956                 (IntRegIndex)_base, _add, _imm)
957    {
958        %(constructor)s;
959        if (!(condCode == COND_AL || condCode == COND_UC)) {
960            for (int x = 0; x < _numDestRegs; x++) {
961                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
962            }
963        }
964#if %(use_uops)d
965        assert(numMicroops >= 2);
966        uops = new StaticInstPtr[numMicroops];
967        uops[0] = new %(acc_name)s(machInst, _result, _dest, _dest2,
968                                   _base, _add, _imm);
969        uops[0]->setDelayedCommit();
970        uops[0]->setFirstMicroop();
971        uops[1] = new %(wb_decl)s;
972        uops[1]->setLastMicroop();
973#endif
974    }
975}};
976
977def template LoadStoreImmConstructor {{
978    %(class_name)s::%(class_name)s(ExtMachInst machInst,
979            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
980         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
981                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
982    {
983        %(constructor)s;
984        if (!(condCode == COND_AL || condCode == COND_UC)) {
985            for (int x = 0; x < _numDestRegs; x++) {
986                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
987            }
988        }
989#if %(use_uops)d
990        assert(numMicroops >= 2);
991        uops = new StaticInstPtr[numMicroops];
992        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
993        uops[0]->setDelayedCommit();
994        uops[0]->setFirstMicroop();
995        uops[1] = new %(wb_decl)s;
996        uops[1]->setLastMicroop();
997#endif
998    }
999}};
1000
1001def template StoreExImmConstructor {{
1002    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1003            uint32_t _result, uint32_t _dest, uint32_t _base,
1004            bool _add, int32_t _imm)
1005         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1006                 (IntRegIndex)_result, (IntRegIndex)_dest,
1007                 (IntRegIndex)_base, _add, _imm)
1008    {
1009        %(constructor)s;
1010        if (!(condCode == COND_AL || condCode == COND_UC)) {
1011            for (int x = 0; x < _numDestRegs; x++) {
1012                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1013            }
1014        }
1015#if %(use_uops)d
1016        assert(numMicroops >= 2);
1017        uops = new StaticInstPtr[numMicroops];
1018        uops[0] = new %(acc_name)s(machInst, _result, _dest,
1019                                   _base, _add, _imm);
1020        uops[0]->setDelayedCommit();
1021        uops[0]->setFirstMicroop();
1022        uops[1] = new %(wb_decl)s;
1023        uops[1]->setLastMicroop();
1024#endif
1025    }
1026}};
1027
1028def template StoreDRegConstructor {{
1029    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1030            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1031            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1032         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1033                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1034                 (IntRegIndex)_base, _add,
1035                 _shiftAmt, (ArmShiftType)_shiftType,
1036                 (IntRegIndex)_index)
1037    {
1038        %(constructor)s;
1039        if (!(condCode == COND_AL || condCode == COND_UC)) {
1040            for (int x = 0; x < _numDestRegs; x++) {
1041                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1042            }
1043        }
1044#if %(use_uops)d
1045        assert(numMicroops >= 2);
1046        uops = new StaticInstPtr[numMicroops];
1047        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1048                                   _shiftAmt, _shiftType, _index);
1049        uops[0]->setDelayedCommit();
1050        uops[0]->setFirstMicroop();
1051        uops[1] = new %(wb_decl)s;
1052        uops[1]->setLastMicroop();
1053#endif
1054    }
1055}};
1056
1057def template StoreRegConstructor {{
1058    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1059            uint32_t _dest, uint32_t _base, bool _add,
1060            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1061         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1062                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1063                 _shiftAmt, (ArmShiftType)_shiftType,
1064                 (IntRegIndex)_index)
1065    {
1066        %(constructor)s;
1067        if (!(condCode == COND_AL || condCode == COND_UC)) {
1068            for (int x = 0; x < _numDestRegs; x++) {
1069                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1070            }
1071        }
1072#if %(use_uops)d
1073        assert(numMicroops >= 2);
1074        uops = new StaticInstPtr[numMicroops];
1075        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1076                                   _shiftAmt, _shiftType, _index);
1077        uops[0]->setDelayedCommit();
1078        uops[0]->setFirstMicroop();
1079        uops[1] = new %(wb_decl)s;
1080        uops[1]->setLastMicroop();
1081#endif
1082    }
1083}};
1084
1085def template LoadDRegConstructor {{
1086    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1087            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1088            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1089         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1090                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1091                 (IntRegIndex)_base, _add,
1092                 _shiftAmt, (ArmShiftType)_shiftType,
1093                 (IntRegIndex)_index)
1094    {
1095        %(constructor)s;
1096        if (!(condCode == COND_AL || condCode == COND_UC)) {
1097            for (int x = 0; x < _numDestRegs; x++) {
1098                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1099            }
1100        }
1101#if %(use_uops)d
1102        assert(numMicroops >= 2);
1103        uops = new StaticInstPtr[numMicroops];
1104        if ((_dest == _index) || (_dest2 == _index)) {
1105            IntRegIndex wbIndexReg = INTREG_UREG0;
1106            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1107            uops[0]->setDelayedCommit();
1108            uops[0]->setFirstMicroop();
1109            uops[1] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1110                                       _shiftAmt, _shiftType, _index);
1111            uops[1]->setDelayedCommit();
1112            uops[2] = new %(wb_decl)s;
1113            uops[2]->setLastMicroop();
1114        } else {
1115            IntRegIndex wbIndexReg = index;
1116            uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1117                                       _shiftAmt, _shiftType, _index);
1118            uops[0]->setDelayedCommit();
1119            uops[0]->setFirstMicroop();
1120            uops[1] = new %(wb_decl)s;
1121            uops[1]->setLastMicroop();
1122        }
1123#endif
1124    }
1125}};
1126
1127def template LoadRegConstructor {{
1128    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1129            uint32_t _dest, uint32_t _base, bool _add,
1130            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1131         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1132                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1133                 _shiftAmt, (ArmShiftType)_shiftType,
1134                 (IntRegIndex)_index)
1135    {
1136        %(constructor)s;
1137        bool conditional M5_VAR_USED = false;
1138        if (!(condCode == COND_AL || condCode == COND_UC)) {
1139            conditional = true;
1140            for (int x = 0; x < _numDestRegs; x++) {
1141                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1142            }
1143        }
1144#if %(use_uops)d
1145        assert(numMicroops >= 2);
1146        uops = new StaticInstPtr[numMicroops];
1147        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1148            IntRegIndex wbIndexReg = index;
1149            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1150                                       _shiftAmt, _shiftType, _index);
1151            uops[0]->setDelayedCommit();
1152            uops[0]->setFirstMicroop();
1153            uops[1] = new %(wb_decl)s;
1154            uops[1]->setDelayedCommit();
1155            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1156            uops[2]->setFlag(StaticInst::IsControl);
1157            uops[2]->setFlag(StaticInst::IsIndirectControl);
1158            if (conditional)
1159                uops[2]->setFlag(StaticInst::IsCondControl);
1160            else
1161                uops[2]->setFlag(StaticInst::IsUncondControl);
1162            uops[2]->setLastMicroop();
1163        } else if(_dest == _index) {
1164            IntRegIndex wbIndexReg = INTREG_UREG0;
1165            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1166            uops[0]->setDelayedCommit();
1167            uops[0]->setFirstMicroop();
1168            uops[1] = new %(acc_name)s(machInst, _dest, _base, _add,
1169                                      _shiftAmt, _shiftType, _index);
1170            uops[1]->setDelayedCommit();
1171            uops[2] = new %(wb_decl)s;
1172            uops[2]->setLastMicroop();
1173        } else {
1174            IntRegIndex wbIndexReg = index;
1175            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1176                                      _shiftAmt, _shiftType, _index);
1177            uops[0]->setDelayedCommit();
1178            uops[0]->setFirstMicroop();
1179            uops[1] = new %(wb_decl)s;
1180            uops[1]->setLastMicroop();
1181
1182        }
1183#else
1184        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1185            flags[IsControl] = true;
1186            flags[IsIndirectControl] = true;
1187            if (conditional)
1188                flags[IsCondControl] = true;
1189            else
1190                flags[IsUncondControl] = true;
1191        }
1192#endif
1193    }
1194}};
1195
1196def template LoadImmConstructor {{
1197    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1198            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
1199         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1200                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
1201    {
1202        %(constructor)s;
1203        bool conditional M5_VAR_USED = false;
1204        if (!(condCode == COND_AL || condCode == COND_UC)) {
1205            conditional = true;
1206            for (int x = 0; x < _numDestRegs; x++) {
1207                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1208            }
1209        }
1210#if %(use_uops)d
1211        assert(numMicroops >= 2);
1212        uops = new StaticInstPtr[numMicroops];
1213        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1214            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1215                                   _imm);
1216            uops[0]->setDelayedCommit();
1217            uops[0]->setFirstMicroop();
1218            uops[1] = new %(wb_decl)s;
1219            uops[1]->setDelayedCommit();
1220            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1221            uops[2]->setFlag(StaticInst::IsControl);
1222            uops[2]->setFlag(StaticInst::IsIndirectControl);
1223            /* Also set flags on the macroop so that pre-microop decomposition
1224                branch prediction can work */
1225            setFlag(StaticInst::IsControl);
1226            setFlag(StaticInst::IsIndirectControl);
1227            if (conditional) {
1228                uops[2]->setFlag(StaticInst::IsCondControl);
1229                setFlag(StaticInst::IsCondControl);
1230            } else {
1231                uops[2]->setFlag(StaticInst::IsUncondControl);
1232                setFlag(StaticInst::IsUncondControl);
1233            }
1234            if (_base == INTREG_SP && _add && _imm == 4 && %(is_ras_pop)s) {
1235                uops[2]->setFlag(StaticInst::IsReturn);
1236                setFlag(StaticInst::IsReturn);
1237            }
1238            uops[2]->setLastMicroop();
1239        } else {
1240            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
1241            uops[0]->setDelayedCommit();
1242            uops[0]->setFirstMicroop();
1243            uops[1] = new %(wb_decl)s;
1244            uops[1]->setLastMicroop();
1245        }
1246#else
1247        if (_dest == INTREG_PC && !isFloating() && !isVector()) {
1248            flags[IsControl] = true;
1249            flags[IsIndirectControl] = true;
1250            if (conditional)
1251                flags[IsCondControl] = true;
1252            else
1253                flags[IsUncondControl] = true;
1254        }
1255#endif
1256    }
1257}};
1258
1259