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