mem.isa revision 10666:3c42be107634
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 = readMemTiming(xc, traceData, EA, Mem, memAccessFlags);
442            }
443        } else {
444            xc->setPredicate(false);
445        }
446
447        return fault;
448    }
449}};
450
451def template NeonLoadInitiateAcc {{
452    template <class Element>
453    Fault %(class_name)s<Element>::initiateAcc(
454            CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
455    {
456        Addr EA;
457        Fault fault = NoFault;
458
459        %(op_decl)s;
460        %(mem_decl)s;
461        %(op_rd)s;
462        %(ea_code)s;
463
464        MemUnion memUnion;
465        uint8_t *dataPtr = memUnion.bytes;
466
467        if (%(predicate_test)s)
468        {
469            if (fault == NoFault) {
470                fault = xc->readMem(EA, dataPtr, %(size)d, memAccessFlags);
471            }
472        } else {
473            xc->setPredicate(false);
474        }
475
476        return fault;
477    }
478}};
479
480def template LoadCompleteAcc {{
481    Fault %(class_name)s::completeAcc(PacketPtr pkt,
482                                      CPU_EXEC_CONTEXT *xc,
483                                      Trace::InstRecord *traceData) const
484    {
485        Fault fault = NoFault;
486
487        %(op_decl)s;
488        %(op_rd)s;
489
490        if (%(predicate_test)s)
491        {
492            // ARM instructions will not have a pkt if the predicate is false
493            getMem(pkt, Mem, traceData);
494
495            if (fault == NoFault) {
496                %(memacc_code)s;
497            }
498
499            if (fault == NoFault) {
500                %(op_wb)s;
501            }
502        }
503
504        return fault;
505    }
506}};
507
508def template NeonLoadCompleteAcc {{
509    template <class Element>
510    Fault %(class_name)s<Element>::completeAcc(
511            PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
512            Trace::InstRecord *traceData) const
513    {
514        Fault fault = NoFault;
515
516        %(mem_decl)s;
517        %(op_decl)s;
518        %(op_rd)s;
519
520        if (%(predicate_test)s)
521        {
522            // ARM instructions will not have a pkt if the predicate is false
523            MemUnion &memUnion = *(MemUnion *)pkt->getPtr<uint8_t>();
524
525            if (fault == NoFault) {
526                %(memacc_code)s;
527            }
528
529            if (fault == NoFault) {
530                %(op_wb)s;
531            }
532        }
533
534        return fault;
535    }
536}};
537
538def template StoreCompleteAcc {{
539    Fault %(class_name)s::completeAcc(PacketPtr pkt,
540                                      CPU_EXEC_CONTEXT *xc,
541                                      Trace::InstRecord *traceData) const
542    {
543        return NoFault;
544    }
545}};
546
547def template NeonStoreCompleteAcc {{
548    template <class Element>
549    Fault %(class_name)s<Element>::completeAcc(
550            PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
551            Trace::InstRecord *traceData) const
552    {
553        return NoFault;
554    }
555}};
556
557def template StoreExCompleteAcc {{
558    Fault %(class_name)s::completeAcc(PacketPtr pkt,
559                                      CPU_EXEC_CONTEXT *xc,
560                                      Trace::InstRecord *traceData) const
561    {
562        Fault fault = NoFault;
563
564        %(op_decl)s;
565        %(op_rd)s;
566
567        if (%(predicate_test)s)
568        {
569            uint64_t writeResult = pkt->req->getExtraData();
570            %(postacc_code)s;
571
572            if (fault == NoFault) {
573                %(op_wb)s;
574            }
575        }
576
577        return fault;
578    }
579}};
580
581def template RfeDeclare {{
582    /**
583     * Static instruction class for "%(mnemonic)s".
584     */
585    class %(class_name)s : public %(base_class)s
586    {
587      public:
588
589        /// Constructor.
590        %(class_name)s(ExtMachInst machInst,
591                uint32_t _base, int _mode, bool _wb);
592
593        %(BasicExecDeclare)s
594
595        %(InitiateAccDeclare)s
596
597        %(CompleteAccDeclare)s
598    };
599}};
600
601def template SrsDeclare {{
602    /**
603     * Static instruction class for "%(mnemonic)s".
604     */
605    class %(class_name)s : public %(base_class)s
606    {
607      public:
608
609        /// Constructor.
610        %(class_name)s(ExtMachInst machInst,
611                uint32_t _regMode, int _mode, bool _wb);
612
613        %(BasicExecDeclare)s
614
615        %(InitiateAccDeclare)s
616
617        %(CompleteAccDeclare)s
618    };
619}};
620
621def template SwapDeclare {{
622    /**
623     * Static instruction class for "%(mnemonic)s".
624     */
625    class %(class_name)s : public %(base_class)s
626    {
627      public:
628
629        /// Constructor.
630        %(class_name)s(ExtMachInst machInst,
631                uint32_t _dest, uint32_t _op1, uint32_t _base);
632
633        %(BasicExecDeclare)s
634
635        %(InitiateAccDeclare)s
636
637        %(CompleteAccDeclare)s
638    };
639}};
640
641def template LoadStoreDImmDeclare {{
642    /**
643     * Static instruction class for "%(mnemonic)s".
644     */
645    class %(class_name)s : public %(base_class)s
646    {
647      public:
648
649        /// Constructor.
650        %(class_name)s(ExtMachInst machInst,
651                uint32_t _dest, uint32_t _dest2,
652                uint32_t _base, bool _add, int32_t _imm);
653
654        %(BasicExecDeclare)s
655
656        %(InitiateAccDeclare)s
657
658        %(CompleteAccDeclare)s
659    };
660}};
661
662def template StoreExDImmDeclare {{
663    /**
664     * Static instruction class for "%(mnemonic)s".
665     */
666    class %(class_name)s : public %(base_class)s
667    {
668      public:
669
670        /// Constructor.
671        %(class_name)s(ExtMachInst machInst,
672                uint32_t _result, uint32_t _dest, uint32_t _dest2,
673                uint32_t _base, bool _add, int32_t _imm);
674
675        %(BasicExecDeclare)s
676
677        %(InitiateAccDeclare)s
678
679        %(CompleteAccDeclare)s
680    };
681}};
682
683def template LoadStoreImmDeclare {{
684    /**
685     * Static instruction class for "%(mnemonic)s".
686     */
687    class %(class_name)s : public %(base_class)s
688    {
689      public:
690
691        /// Constructor.
692        %(class_name)s(ExtMachInst machInst,
693                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
694
695        %(BasicExecDeclare)s
696
697        %(InitiateAccDeclare)s
698
699        %(CompleteAccDeclare)s
700
701        virtual void
702        annotateFault(ArmFault *fault) {
703            %(fa_code)s
704        }
705    };
706}};
707
708def template StoreExImmDeclare {{
709    /**
710     * Static instruction class for "%(mnemonic)s".
711     */
712    class %(class_name)s : public %(base_class)s
713    {
714      public:
715
716        /// Constructor.
717        %(class_name)s(ExtMachInst machInst,
718                uint32_t _result, uint32_t _dest, uint32_t _base,
719                bool _add, int32_t _imm);
720
721        %(BasicExecDeclare)s
722
723        %(InitiateAccDeclare)s
724
725        %(CompleteAccDeclare)s
726    };
727}};
728
729def template StoreDRegDeclare {{
730    /**
731     * Static instruction class for "%(mnemonic)s".
732     */
733    class %(class_name)s : public %(base_class)s
734    {
735      public:
736
737        /// Constructor.
738        %(class_name)s(ExtMachInst machInst,
739                uint32_t _dest, uint32_t _dest2,
740                uint32_t _base, bool _add,
741                int32_t _shiftAmt, uint32_t _shiftType,
742                uint32_t _index);
743
744        %(BasicExecDeclare)s
745
746        %(InitiateAccDeclare)s
747
748        %(CompleteAccDeclare)s
749    };
750}};
751
752def template StoreRegDeclare {{
753    /**
754     * Static instruction class for "%(mnemonic)s".
755     */
756    class %(class_name)s : public %(base_class)s
757    {
758      public:
759
760        /// Constructor.
761        %(class_name)s(ExtMachInst machInst,
762                uint32_t _dest, uint32_t _base, bool _add,
763                int32_t _shiftAmt, uint32_t _shiftType,
764                uint32_t _index);
765
766        %(BasicExecDeclare)s
767
768        %(InitiateAccDeclare)s
769
770        %(CompleteAccDeclare)s
771
772        virtual void
773        annotateFault(ArmFault *fault) {
774            %(fa_code)s
775        }
776    };
777}};
778
779def template LoadDRegDeclare {{
780    /**
781     * Static instruction class for "%(mnemonic)s".
782     */
783    class %(class_name)s : public %(base_class)s
784    {
785      public:
786
787        /// Constructor.
788        %(class_name)s(ExtMachInst machInst,
789                uint32_t _dest, uint32_t _dest2,
790                uint32_t _base, bool _add,
791                int32_t _shiftAmt, uint32_t _shiftType,
792                uint32_t _index);
793
794        %(BasicExecDeclare)s
795
796        %(InitiateAccDeclare)s
797
798        %(CompleteAccDeclare)s
799    };
800}};
801
802def template LoadRegDeclare {{
803    /**
804     * Static instruction class for "%(mnemonic)s".
805     */
806    class %(class_name)s : public %(base_class)s
807    {
808      public:
809
810        /// Constructor.
811        %(class_name)s(ExtMachInst machInst,
812                uint32_t _dest, uint32_t _base, bool _add,
813                int32_t _shiftAmt, uint32_t _shiftType,
814                uint32_t _index);
815
816        %(BasicExecDeclare)s
817
818        %(InitiateAccDeclare)s
819
820        %(CompleteAccDeclare)s
821
822        virtual void
823        annotateFault(ArmFault *fault) {
824            %(fa_code)s
825        }
826    };
827}};
828
829def template LoadImmDeclare {{
830    /**
831     * Static instruction class for "%(mnemonic)s".
832     */
833    class %(class_name)s : public %(base_class)s
834    {
835      public:
836
837        /// Constructor.
838        %(class_name)s(ExtMachInst machInst,
839                uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
840
841        %(BasicExecDeclare)s
842
843        %(InitiateAccDeclare)s
844
845        %(CompleteAccDeclare)s
846
847        virtual void
848        annotateFault(ArmFault *fault) {
849            %(fa_code)s
850        }
851    };
852}};
853
854def template InitiateAccDeclare {{
855    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
856}};
857
858def template CompleteAccDeclare {{
859    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
860}};
861
862def template RfeConstructor {{
863    %(class_name)s::%(class_name)s(ExtMachInst machInst,
864                                          uint32_t _base, int _mode, bool _wb)
865        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
866                         (IntRegIndex)_base, (AddrMode)_mode, _wb)
867    {
868        %(constructor)s;
869        if (!(condCode == COND_AL || condCode == COND_UC)) {
870            for (int x = 0; x < _numDestRegs; x++) {
871                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
872            }
873        }
874#if %(use_uops)d
875        uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
876        int uopIdx = 0;
877        uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
878        uops[uopIdx]->setDelayedCommit();
879#if %(use_wb)d
880        uops[++uopIdx] = new %(wb_decl)s;
881        uops[uopIdx]->setDelayedCommit();
882#endif
883#if %(use_pc)d
884        uops[++uopIdx] = new %(pc_decl)s;
885#endif
886        uops[0]->setFirstMicroop();
887        uops[uopIdx]->setLastMicroop();
888#endif
889    }
890}};
891
892def template SrsConstructor {{
893    %(class_name)s::%(class_name)s(ExtMachInst machInst,
894            uint32_t _regMode, int _mode, bool _wb)
895         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
896                 (OperatingMode)_regMode, (AddrMode)_mode, _wb)
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#if %(use_uops)d
905        assert(numMicroops >= 2);
906        uops = new StaticInstPtr[numMicroops];
907        uops[0] = new %(acc_name)s(machInst, _regMode, _mode, _wb);
908        uops[0]->setDelayedCommit();
909        uops[0]->setFirstMicroop();
910        uops[1] = new %(wb_decl)s;
911        uops[1]->setLastMicroop();
912#endif
913    }
914}};
915
916def template SwapConstructor {{
917    %(class_name)s::%(class_name)s(ExtMachInst machInst,
918            uint32_t _dest, uint32_t _op1, uint32_t _base)
919         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
920                 (IntRegIndex)_dest, (IntRegIndex)_op1, (IntRegIndex)_base)
921    {
922        %(constructor)s;
923        if (!(condCode == COND_AL || condCode == COND_UC)) {
924            for (int x = 0; x < _numDestRegs; x++) {
925                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
926            }
927        }
928    }
929}};
930
931def template LoadStoreDImmConstructor {{
932    %(class_name)s::%(class_name)s(ExtMachInst machInst,
933            uint32_t _dest, uint32_t _dest2,
934            uint32_t _base, bool _add, int32_t _imm)
935         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
936                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
937                 (IntRegIndex)_base, _add, _imm)
938    {
939        %(constructor)s;
940        if (!(condCode == COND_AL || condCode == COND_UC)) {
941            for (int x = 0; x < _numDestRegs; x++) {
942                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
943            }
944        }
945#if %(use_uops)d
946        assert(numMicroops >= 2);
947        uops = new StaticInstPtr[numMicroops];
948        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add, _imm);
949        uops[0]->setFirstMicroop();
950        uops[0]->setDelayedCommit();
951        uops[1] = new %(wb_decl)s;
952        uops[1]->setLastMicroop();
953#endif
954    }
955}};
956
957def template StoreExDImmConstructor {{
958    %(class_name)s::%(class_name)s(ExtMachInst machInst,
959            uint32_t _result, uint32_t _dest, uint32_t _dest2,
960            uint32_t _base, bool _add, int32_t _imm)
961         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
962                 (IntRegIndex)_result,
963                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
964                 (IntRegIndex)_base, _add, _imm)
965    {
966        %(constructor)s;
967        if (!(condCode == COND_AL || condCode == COND_UC)) {
968            for (int x = 0; x < _numDestRegs; x++) {
969                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
970            }
971        }
972#if %(use_uops)d
973        assert(numMicroops >= 2);
974        uops = new StaticInstPtr[numMicroops];
975        uops[0] = new %(acc_name)s(machInst, _result, _dest, _dest2,
976                                   _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 LoadStoreImmConstructor {{
986    %(class_name)s::%(class_name)s(ExtMachInst machInst,
987            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
988         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
989                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
990    {
991        %(constructor)s;
992        if (!(condCode == COND_AL || condCode == COND_UC)) {
993            for (int x = 0; x < _numDestRegs; x++) {
994                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
995            }
996        }
997#if %(use_uops)d
998        assert(numMicroops >= 2);
999        uops = new StaticInstPtr[numMicroops];
1000        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
1001        uops[0]->setDelayedCommit();
1002        uops[0]->setFirstMicroop();
1003        uops[1] = new %(wb_decl)s;
1004        uops[1]->setLastMicroop();
1005#endif
1006    }
1007}};
1008
1009def template StoreExImmConstructor {{
1010    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1011            uint32_t _result, uint32_t _dest, uint32_t _base,
1012            bool _add, int32_t _imm)
1013         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1014                 (IntRegIndex)_result, (IntRegIndex)_dest,
1015                 (IntRegIndex)_base, _add, _imm)
1016    {
1017        %(constructor)s;
1018        if (!(condCode == COND_AL || condCode == COND_UC)) {
1019            for (int x = 0; x < _numDestRegs; x++) {
1020                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1021            }
1022        }
1023#if %(use_uops)d
1024        assert(numMicroops >= 2);
1025        uops = new StaticInstPtr[numMicroops];
1026        uops[0] = new %(acc_name)s(machInst, _result, _dest,
1027                                   _base, _add, _imm);
1028        uops[0]->setDelayedCommit();
1029        uops[0]->setFirstMicroop();
1030        uops[1] = new %(wb_decl)s;
1031        uops[1]->setLastMicroop();
1032#endif
1033    }
1034}};
1035
1036def template StoreDRegConstructor {{
1037    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1038            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1039            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1040         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1041                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1042                 (IntRegIndex)_base, _add,
1043                 _shiftAmt, (ArmShiftType)_shiftType,
1044                 (IntRegIndex)_index)
1045    {
1046        %(constructor)s;
1047        if (!(condCode == COND_AL || condCode == COND_UC)) {
1048            for (int x = 0; x < _numDestRegs; x++) {
1049                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1050            }
1051        }
1052#if %(use_uops)d
1053        assert(numMicroops >= 2);
1054        uops = new StaticInstPtr[numMicroops];
1055        uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1056                                   _shiftAmt, _shiftType, _index);
1057        uops[0]->setDelayedCommit();
1058        uops[0]->setFirstMicroop();
1059        uops[1] = new %(wb_decl)s;
1060        uops[1]->setLastMicroop();
1061#endif
1062    }
1063}};
1064
1065def template StoreRegConstructor {{
1066    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1067            uint32_t _dest, uint32_t _base, bool _add,
1068            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1069         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1070                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1071                 _shiftAmt, (ArmShiftType)_shiftType,
1072                 (IntRegIndex)_index)
1073    {
1074        %(constructor)s;
1075        if (!(condCode == COND_AL || condCode == COND_UC)) {
1076            for (int x = 0; x < _numDestRegs; x++) {
1077                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1078            }
1079        }
1080#if %(use_uops)d
1081        assert(numMicroops >= 2);
1082        uops = new StaticInstPtr[numMicroops];
1083        uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1084                                   _shiftAmt, _shiftType, _index);
1085        uops[0]->setDelayedCommit();
1086        uops[0]->setFirstMicroop();
1087        uops[1] = new %(wb_decl)s;
1088        uops[1]->setLastMicroop();
1089#endif
1090    }
1091}};
1092
1093def template LoadDRegConstructor {{
1094    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1095            uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
1096            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1097         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1098                 (IntRegIndex)_dest, (IntRegIndex)_dest2,
1099                 (IntRegIndex)_base, _add,
1100                 _shiftAmt, (ArmShiftType)_shiftType,
1101                 (IntRegIndex)_index)
1102    {
1103        %(constructor)s;
1104        if (!(condCode == COND_AL || condCode == COND_UC)) {
1105            for (int x = 0; x < _numDestRegs; x++) {
1106                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1107            }
1108        }
1109#if %(use_uops)d
1110        assert(numMicroops >= 2);
1111        uops = new StaticInstPtr[numMicroops];
1112        if ((_dest == _index) || (_dest2 == _index)) {
1113            IntRegIndex wbIndexReg = INTREG_UREG0;
1114            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1115            uops[0]->setDelayedCommit();
1116            uops[0]->setFirstMicroop();
1117            uops[1] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1118                                       _shiftAmt, _shiftType, _index);
1119            uops[1]->setDelayedCommit();
1120            uops[2] = new %(wb_decl)s;
1121            uops[2]->setLastMicroop();
1122        } else {
1123            IntRegIndex wbIndexReg = index;
1124            uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
1125                                       _shiftAmt, _shiftType, _index);
1126            uops[0]->setDelayedCommit();
1127            uops[0]->setFirstMicroop();
1128            uops[1] = new %(wb_decl)s;
1129            uops[1]->setLastMicroop();
1130        }
1131#endif
1132    }
1133}};
1134
1135def template LoadRegConstructor {{
1136    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1137            uint32_t _dest, uint32_t _base, bool _add,
1138            int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
1139         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1140                 (IntRegIndex)_dest, (IntRegIndex)_base, _add,
1141                 _shiftAmt, (ArmShiftType)_shiftType,
1142                 (IntRegIndex)_index)
1143    {
1144        %(constructor)s;
1145        bool conditional M5_VAR_USED = false;
1146        if (!(condCode == COND_AL || condCode == COND_UC)) {
1147            conditional = true;
1148            for (int x = 0; x < _numDestRegs; x++) {
1149                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1150            }
1151        }
1152#if %(use_uops)d
1153        assert(numMicroops >= 2);
1154        uops = new StaticInstPtr[numMicroops];
1155        if (_dest == INTREG_PC && !isFloating()) {
1156            IntRegIndex wbIndexReg = index;
1157            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1158                                       _shiftAmt, _shiftType, _index);
1159            uops[0]->setDelayedCommit();
1160            uops[0]->setFirstMicroop();
1161            uops[1] = new %(wb_decl)s;
1162            uops[1]->setDelayedCommit();
1163            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1164            uops[2]->setFlag(StaticInst::IsControl);
1165            uops[2]->setFlag(StaticInst::IsIndirectControl);
1166            if (conditional)
1167                uops[2]->setFlag(StaticInst::IsCondControl);
1168            else
1169                uops[2]->setFlag(StaticInst::IsUncondControl);
1170            uops[2]->setLastMicroop();
1171        } else if(_dest == _index) {
1172            IntRegIndex wbIndexReg = INTREG_UREG0;
1173            uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
1174            uops[0]->setDelayedCommit();
1175            uops[0]->setFirstMicroop();
1176            uops[1] = new %(acc_name)s(machInst, _dest, _base, _add,
1177                                      _shiftAmt, _shiftType, _index);
1178            uops[1]->setDelayedCommit();
1179            uops[2] = new %(wb_decl)s;
1180            uops[2]->setLastMicroop();
1181        } else {
1182            IntRegIndex wbIndexReg = index;
1183            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
1184                                      _shiftAmt, _shiftType, _index);
1185            uops[0]->setDelayedCommit();
1186            uops[0]->setFirstMicroop();
1187            uops[1] = new %(wb_decl)s;
1188            uops[1]->setLastMicroop();
1189
1190        }
1191#else
1192        if (_dest == INTREG_PC && !isFloating()) {
1193            flags[IsControl] = true;
1194            flags[IsIndirectControl] = true;
1195            if (conditional)
1196                flags[IsCondControl] = true;
1197            else
1198                flags[IsUncondControl] = true;
1199        }
1200#endif
1201    }
1202}};
1203
1204def template LoadImmConstructor {{
1205    %(class_name)s::%(class_name)s(ExtMachInst machInst,
1206            uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
1207         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
1208                 (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
1209    {
1210        %(constructor)s;
1211        bool conditional M5_VAR_USED = false;
1212        if (!(condCode == COND_AL || condCode == COND_UC)) {
1213            conditional = true;
1214            for (int x = 0; x < _numDestRegs; x++) {
1215                _srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
1216            }
1217        }
1218#if %(use_uops)d
1219        assert(numMicroops >= 2);
1220        uops = new StaticInstPtr[numMicroops];
1221        if (_dest == INTREG_PC && !isFloating()) {
1222            uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
1223                                   _imm);
1224            uops[0]->setDelayedCommit();
1225            uops[0]->setFirstMicroop();
1226            uops[1] = new %(wb_decl)s;
1227            uops[1]->setDelayedCommit();
1228            uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
1229            uops[2]->setFlag(StaticInst::IsControl);
1230            uops[2]->setFlag(StaticInst::IsIndirectControl);
1231            /* Also set flags on the macroop so that pre-microop decomposition
1232                branch prediction can work */
1233            setFlag(StaticInst::IsControl);
1234            setFlag(StaticInst::IsIndirectControl);
1235            if (conditional) {
1236                uops[2]->setFlag(StaticInst::IsCondControl);
1237                setFlag(StaticInst::IsCondControl);
1238            } else {
1239                uops[2]->setFlag(StaticInst::IsUncondControl);
1240                setFlag(StaticInst::IsUncondControl);
1241            }
1242            if (_base == INTREG_SP && _add && _imm == 4 && %(is_ras_pop)s) {
1243                uops[2]->setFlag(StaticInst::IsReturn);
1244                setFlag(StaticInst::IsReturn);
1245            }
1246            uops[2]->setLastMicroop();
1247        } else {
1248            uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
1249            uops[0]->setDelayedCommit();
1250            uops[0]->setFirstMicroop();
1251            uops[1] = new %(wb_decl)s;
1252            uops[1]->setLastMicroop();
1253        }
1254#else
1255        if (_dest == INTREG_PC && !isFloating()) {
1256            flags[IsControl] = true;
1257            flags[IsIndirectControl] = true;
1258            if (conditional)
1259                flags[IsCondControl] = true;
1260            else
1261                flags[IsUncondControl] = true;
1262        }
1263#endif
1264    }
1265}};
1266
1267