mem.isa revision 5268:5bfc53fe60e7
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007 MIPS Technologies, Inc.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Steve Reinhardt
30//          Korey Sewell
31
32////////////////////////////////////////////////////////////////////
33//
34// Memory-format instructions
35//
36
37output header {{
38    /**
39     * Base class for general Mips memory-format instructions.
40     */
41    class Memory : public MipsStaticInst
42    {
43      protected:
44
45        /// Memory request flags.  See mem_req_base.hh.
46        unsigned memAccessFlags;
47        /// Pointer to EAComp object.
48        const StaticInstPtr eaCompPtr;
49        /// Pointer to MemAcc object.
50        const StaticInstPtr memAccPtr;
51
52        /// Displacement for EA calculation (signed).
53        int32_t disp;
54
55        /// Constructor
56        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
57               StaticInstPtr _eaCompPtr = nullStaticInstPtr,
58               StaticInstPtr _memAccPtr = nullStaticInstPtr)
59            : MipsStaticInst(mnem, _machInst, __opClass),
60              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
61              disp(sext<16>(OFFSET))
62        {
63        }
64
65        std::string
66        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
67
68      public:
69
70        const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
71        const StaticInstPtr &memAccInst() const { return memAccPtr; }
72
73        unsigned memAccFlags() { return memAccessFlags; }
74    };
75
76     /**
77     * Base class for a few miscellaneous memory-format insts
78     * that don't interpret the disp field
79     */
80    class MemoryNoDisp : public Memory
81    {
82      protected:
83        /// Constructor
84        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
85                     StaticInstPtr _eaCompPtr = nullStaticInstPtr,
86                     StaticInstPtr _memAccPtr = nullStaticInstPtr)
87            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
88        {
89        }
90
91        std::string
92        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
93    };
94}};
95
96
97output decoder {{
98    std::string
99    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
100    {
101        return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
102                        flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
103    }
104
105    std::string
106    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
107    {
108        return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
109                        flags[IsFloating] ? 'f' : 'r',
110                        flags[IsFloating] ? FD : RD,
111                        RS, RT);
112    }
113
114}};
115
116output exec {{
117    /** return data in cases where there the size of data is only
118        known in the packet
119    */
120    uint64_t getMemData(%(CPU_exec_context)s *xc, Packet *packet) {
121        switch (packet->getSize())
122        {
123          case 1:
124            return packet->get<uint8_t>();
125
126          case 2:
127            return packet->get<uint16_t>();
128
129          case 4:
130            return packet->get<uint32_t>();
131
132          case 8:
133            return packet->get<uint64_t>();
134
135          default:
136            std::cerr << "bad store data size = " << packet->getSize() << std::endl;
137
138            assert(0);
139            return 0;
140        }
141    }
142
143
144}};
145
146def template LoadStoreDeclare {{
147    /**
148     * Static instruction class for "%(mnemonic)s".
149     */
150    class %(class_name)s : public %(base_class)s
151    {
152      protected:
153
154        /**
155         * "Fake" effective address computation class for "%(mnemonic)s".
156         */
157        class EAComp : public %(base_class)s
158        {
159          public:
160            /// Constructor
161            EAComp(ExtMachInst machInst);
162
163            %(BasicExecDeclare)s
164        };
165
166        /**
167         * "Fake" memory access instruction class for "%(mnemonic)s".
168         */
169        class MemAcc : public %(base_class)s
170        {
171          public:
172            /// Constructor
173            MemAcc(ExtMachInst machInst);
174
175            %(BasicExecDeclare)s
176        };
177
178      public:
179
180        /// Constructor.
181        %(class_name)s(ExtMachInst machInst);
182
183        %(BasicExecDeclare)s
184
185        %(InitiateAccDeclare)s
186
187        %(CompleteAccDeclare)s
188
189        %(MemAccSizeDeclare)s
190    };
191}};
192
193
194def template InitiateAccDeclare {{
195    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
196}};
197
198
199def template CompleteAccDeclare {{
200    Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
201}};
202
203def template MemAccSizeDeclare {{
204    int memAccSize(%(CPU_exec_context)s *xc);
205}};
206
207
208def template MiscMemAccSize {{
209    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
210    {
211        panic("Misc instruction does not support split access method!");
212        return 0;
213    }
214}};
215
216def template EACompConstructor {{
217    /** TODO: change op_class to AddrGenOp or something (requires
218     * creating new member of OpClass enum in op_class.hh, updating
219     * config files, etc.). */
220    inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
221        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
222    {
223        %(constructor)s;
224    }
225}};
226
227
228def template MemAccConstructor {{
229    inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
230        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
231    {
232        %(constructor)s;
233    }
234}};
235
236
237def template LoadStoreConstructor {{
238    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
239         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
240                          new EAComp(machInst), new MemAcc(machInst))
241    {
242        %(constructor)s;
243    }
244}};
245
246
247def template EACompExecute {{
248    Fault
249    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
250                                   Trace::InstRecord *traceData) const
251    {
252        Addr EA;
253        Fault fault = NoFault;
254
255        if (this->isFloating()) {
256            %(fp_enable_check)s;
257
258            if(fault != NoFault)
259                return fault;
260        }
261
262        %(op_decl)s;
263        %(op_rd)s;
264        %(ea_code)s;
265
266        // NOTE: Trace Data is written using execute or completeAcc templates
267        if (fault == NoFault) {
268            xc->setEA(EA);
269        }
270
271        return fault;
272    }
273}};
274
275def template LoadStoreFPEACompExecute {{
276    Fault
277    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
278                                   Trace::InstRecord *traceData) const
279    {
280        Addr EA;
281        Fault fault = NoFault;
282
283        %(fp_enable_check)s;
284        if(fault != NoFault)
285          return fault;
286        %(op_decl)s;
287        %(op_rd)s;
288        %(ea_code)s;
289
290        // NOTE: Trace Data is written using execute or completeAcc templates
291        if (fault == NoFault) {
292            xc->setEA(EA);
293        }
294
295        return fault;
296    }
297}};
298
299
300def template LoadMemAccExecute {{
301    Fault
302    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
303                                   Trace::InstRecord *traceData) const
304    {
305        Addr EA;
306
307        Fault fault = NoFault;
308
309        if (this->isFloating()) {
310            %(fp_enable_check)s;
311
312            if(fault != NoFault)
313                return fault;
314        }
315
316        %(op_decl)s;
317        %(op_rd)s;
318
319        EA = xc->getEA();
320
321        fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
322
323        %(memacc_code)s;
324
325        // NOTE: Write back data using execute or completeAcc templates
326
327        return fault;
328    }
329}};
330
331
332def template LoadExecute {{
333    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
334                                  Trace::InstRecord *traceData) const
335    {
336        Addr EA;
337        Fault fault = NoFault;
338
339        if (this->isFloating()) {
340            %(fp_enable_check)s;
341
342            if(fault != NoFault)
343                return fault;
344        }
345
346        %(op_decl)s;
347        %(op_rd)s;
348        %(ea_code)s;
349
350        if (fault == NoFault) {
351            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
352            %(memacc_code)s;
353        }
354
355        if (fault == NoFault) {
356            %(op_wb)s;
357        }
358
359        return fault;
360    }
361}};
362
363
364def template LoadInitiateAcc {{
365    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
366                                      Trace::InstRecord *traceData) const
367    {
368        Addr EA;
369        Fault fault = NoFault;
370
371        if (this->isFloating()) {
372            %(fp_enable_check)s;
373
374            if(fault != NoFault)
375                return fault;
376        }
377
378        %(op_src_decl)s;
379        %(op_rd)s;
380        %(ea_code)s;
381
382        if (fault == NoFault) {
383            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
384        }
385
386        return fault;
387    }
388}};
389
390def template LoadCompleteAcc {{
391    Fault %(class_name)s::completeAcc(Packet *pkt,
392                                      %(CPU_exec_context)s *xc,
393                                      Trace::InstRecord *traceData) const
394    {
395        Fault fault = NoFault;
396
397        if (this->isFloating()) {
398            %(fp_enable_check)s;
399
400            if(fault != NoFault)
401                return fault;
402        }
403
404        %(op_decl)s;
405        %(op_rd)s;
406
407        Mem = pkt->get<typeof(Mem)>();
408
409        if (fault == NoFault) {
410            %(memacc_code)s;
411        }
412
413        if (fault == NoFault) {
414            %(op_wb)s;
415        }
416
417        return fault;
418    }
419}};
420
421
422def template LoadStoreMemAccSize {{
423    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
424    {
425        // Return the memory access size in bytes
426        return (%(mem_acc_size)d / 8);
427    }
428}};
429
430def template StoreMemAccExecute {{
431    Fault
432    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
433                                   Trace::InstRecord *traceData) const
434    {
435        Addr EA;
436        Fault fault = NoFault;
437
438        %(fp_enable_check)s;
439        %(op_decl)s;
440        %(op_rd)s;
441
442        EA = xc->getEA();
443
444        if (fault == NoFault) {
445            %(memacc_code)s;
446        }
447
448        if (fault == NoFault) {
449            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
450                              memAccessFlags, NULL);
451            // @NOTE: Need to Call Complete Access to Set Trace Data
452            //if (traceData) { traceData->setData(Mem); }
453        }
454
455        return fault;
456    }
457}};
458
459def template StoreCondMemAccExecute {{
460    Fault
461    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
462                                   Trace::InstRecord *traceData) const
463    {
464        Addr EA;
465        Fault fault = NoFault;
466        uint64_t write_result = 0;
467
468        %(fp_enable_check)s;
469        %(op_decl)s;
470        %(op_rd)s;
471        EA = xc->getEA();
472
473        if (fault == NoFault) {
474            %(memacc_code)s;
475        }
476
477        if (fault == NoFault) {
478            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
479                              memAccessFlags, &write_result);
480            if (traceData) { traceData->setData(Mem); }
481        }
482
483        if (fault == NoFault) {
484            %(postacc_code)s;
485        }
486
487        if (fault == NoFault) {
488            %(op_wb)s;
489        }
490
491        return fault;
492    }
493}};
494
495def template StoreExecute {{
496    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
497                                  Trace::InstRecord *traceData) const
498    {
499        Addr EA;
500        Fault fault = NoFault;
501
502        %(fp_enable_check)s;
503        %(op_decl)s;
504        %(op_rd)s;
505        %(ea_code)s;
506
507        if (fault == NoFault) {
508            %(memacc_code)s;
509        }
510
511        if (fault == NoFault) {
512            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
513                              memAccessFlags, NULL);
514            if (traceData) { traceData->setData(Mem); }
515        }
516
517        if (fault == NoFault) {
518            %(postacc_code)s;
519        }
520
521        if (fault == NoFault) {
522            %(op_wb)s;
523        }
524
525        return fault;
526    }
527}};
528
529
530def template StoreFPExecute {{
531    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
532                                  Trace::InstRecord *traceData) const
533    {
534        Addr EA;
535        Fault fault = NoFault;
536
537        %(fp_enable_check)s;
538        if(fault != NoFault)
539          return fault;
540        %(op_decl)s;
541        %(op_rd)s;
542        %(ea_code)s;
543
544        if (fault == NoFault) {
545            %(memacc_code)s;
546        }
547
548        if (fault == NoFault) {
549            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
550                              memAccessFlags, NULL);
551            if (traceData) { traceData->setData(Mem); }
552        }
553
554        if (fault == NoFault) {
555            %(postacc_code)s;
556        }
557
558        if (fault == NoFault) {
559            %(op_wb)s;
560        }
561
562        return fault;
563    }
564}};
565
566def template StoreCondExecute {{
567    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
568                                  Trace::InstRecord *traceData) const
569    {
570        Addr EA;
571        Fault fault = NoFault;
572        uint64_t write_result = 0;
573
574        %(fp_enable_check)s;
575        %(op_decl)s;
576        %(op_rd)s;
577        %(ea_code)s;
578
579        if (fault == NoFault) {
580            %(memacc_code)s;
581        }
582
583        if (fault == NoFault) {
584            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
585                              memAccessFlags, &write_result);
586            if (traceData) { traceData->setData(Mem); }
587        }
588
589        if (fault == NoFault) {
590            %(postacc_code)s;
591        }
592
593        if (fault == NoFault) {
594            %(op_wb)s;
595        }
596
597        return fault;
598    }
599}};
600
601def template StoreInitiateAcc {{
602    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
603                                      Trace::InstRecord *traceData) const
604    {
605        Addr EA;
606        Fault fault = NoFault;
607
608        %(fp_enable_check)s;
609        %(op_decl)s;
610        %(op_rd)s;
611        %(ea_code)s;
612
613        if (fault == NoFault) {
614            %(memacc_code)s;
615        }
616
617        if (fault == NoFault) {
618            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
619                              memAccessFlags, NULL);
620            if (traceData) { traceData->setData(Mem); }
621        }
622
623        return fault;
624    }
625}};
626
627
628def template StoreCompleteAcc {{
629    Fault %(class_name)s::completeAcc(Packet *pkt,
630                                      %(CPU_exec_context)s *xc,
631                                      Trace::InstRecord *traceData) const
632    {
633        Fault fault = NoFault;
634
635        %(fp_enable_check)s;
636        %(op_dest_decl)s;
637
638        if (fault == NoFault) {
639            %(postacc_code)s;
640        }
641
642        if (fault == NoFault) {
643            %(op_wb)s;
644
645            if (traceData) { traceData->setData(getMemData(xc, pkt)); }
646        }
647
648        return fault;
649    }
650}};
651
652
653def template StoreCompleteAcc {{
654    Fault %(class_name)s::completeAcc(Packet *pkt,
655                                      %(CPU_exec_context)s *xc,
656                                      Trace::InstRecord *traceData) const
657    {
658        Fault fault = NoFault;
659
660        %(op_dest_decl)s;
661
662        if (fault == NoFault) {
663            %(postacc_code)s;
664        }
665
666        if (fault == NoFault) {
667            %(op_wb)s;
668
669            if (traceData) { traceData->setData(getMemData(xc, pkt)); }
670        }
671
672        return fault;
673    }
674}};
675
676def template StoreCondCompleteAcc {{
677    Fault %(class_name)s::completeAcc(Packet *pkt,
678                                      %(CPU_exec_context)s *xc,
679                                      Trace::InstRecord *traceData) const
680    {
681        Fault fault = NoFault;
682
683        %(fp_enable_check)s;
684        %(op_dest_decl)s;
685
686        uint64_t write_result = pkt->req->getExtraData();
687
688        if (fault == NoFault) {
689            %(postacc_code)s;
690        }
691
692        if (fault == NoFault) {
693            %(op_wb)s;
694        }
695
696        return fault;
697    }
698}};
699
700
701def template MiscMemAccExecute {{
702    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
703                                          Trace::InstRecord *traceData) const
704    {
705        Addr EA;
706        Fault fault = NoFault;
707
708        %(fp_enable_check)s;
709        %(op_decl)s;
710        %(op_rd)s;
711        EA = xc->getEA();
712
713        if (fault == NoFault) {
714            %(memacc_code)s;
715        }
716
717        return NoFault;
718    }
719}};
720
721def template MiscExecute {{
722    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
723                                  Trace::InstRecord *traceData) const
724    {
725        Addr EA;
726        Fault fault = NoFault;
727
728        %(fp_enable_check)s;
729        %(op_decl)s;
730        %(op_rd)s;
731        %(ea_code)s;
732
733        if (fault == NoFault) {
734            %(memacc_code)s;
735        }
736
737        return NoFault;
738    }
739}};
740
741def template MiscInitiateAcc {{
742    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
743                                      Trace::InstRecord *traceData) const
744    {
745        panic("Misc instruction does not support split access method!");
746        return NoFault;
747    }
748}};
749
750
751def template MiscCompleteAcc {{
752    Fault %(class_name)s::completeAcc(Packet *pkt,
753                                      %(CPU_exec_context)s *xc,
754                                      Trace::InstRecord *traceData) const
755    {
756        panic("Misc instruction does not support split access method!");
757
758        return NoFault;
759    }
760}};
761
762
763def template MiscMemAccSize {{
764    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
765    {
766        panic("Misc instruction does not support split access method!");
767        return 0;
768    }
769}};
770
771def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
772                     mem_flags = [], inst_flags = []) {{
773    (header_output, decoder_output, decode_block, exec_output) = \
774        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
775                      decode_template = ImmNopCheckDecode,
776                      exec_template_base = 'Load')
777}};
778
779
780def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
781                     mem_flags = [], inst_flags = []) {{
782    (header_output, decoder_output, decode_block, exec_output) = \
783        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
784                      exec_template_base = 'Store')
785}};
786
787def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
788                     mem_flags = [], inst_flags = []) {{
789    inst_flags += ['IsIndexed']
790    (header_output, decoder_output, decode_block, exec_output) = \
791        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
792                      decode_template = ImmNopCheckDecode,
793                      exec_template_base = 'Load')
794}};
795
796def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
797                     mem_flags = [], inst_flags = []) {{
798    inst_flags += ['IsIndexed']
799    (header_output, decoder_output, decode_block, exec_output) = \
800        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
801                      exec_template_base = 'Store')
802}};
803
804def format LoadFPIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
805                     mem_flags = [], inst_flags = []) {{
806    inst_flags += ['IsIndexed', 'IsFloating']
807    (header_output, decoder_output, decode_block, exec_output) = \
808        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
809                      decode_template = ImmNopCheckDecode,
810                      exec_template_base = 'Load')
811}};
812
813def format StoreFPIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
814                     mem_flags = [], inst_flags = []) {{
815    inst_flags += ['IsIndexed', 'IsFloating']
816    (header_output, decoder_output, decode_block, exec_output) = \
817        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
818                      exec_template_base = 'Store')
819}};
820
821
822def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
823                     mem_flags = [], inst_flags = []) {{
824    decl_code = 'uint32_t mem_word = Mem.uw;\n'
825    decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
826    decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
827    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
828    decl_code += '\tbyte_offset ^= 3;\n'
829    decl_code += '#endif\n'
830
831    memacc_code = decl_code + memacc_code
832
833    (header_output, decoder_output, decode_block, exec_output) = \
834        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
835                      decode_template = ImmNopCheckDecode,
836                      exec_template_base = 'Load')
837}};
838
839def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
840                     mem_flags = [], inst_flags = []) {{
841    decl_code = 'uint32_t mem_word = 0;\n'
842    decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
843    decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
844    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
845    decl_code += '\tbyte_offset ^= 3;\n'
846    decl_code += '#endif\n'
847    decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
848    #decl_code += 'xc->readFunctional(EA,(uint32_t&)mem_word);'
849    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
850
851    (header_output, decoder_output, decode_block, exec_output) = \
852        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
853                      exec_template_base = 'Store')
854}};
855
856def format Prefetch(ea_code = {{ EA = Rs + disp; }},
857                          mem_flags = [], pf_flags = [], inst_flags = []) {{
858    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
859    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
860                                  'IsDataPrefetch', 'MemReadOp']
861
862    (header_output, decoder_output, decode_block, exec_output) = \
863        LoadStoreBase(name, Name, ea_code,
864                      'xc->prefetch(EA, memAccessFlags);',
865                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
866
867}};
868
869def format StoreCond(memacc_code, postacc_code,
870                     ea_code = {{ EA = Rs + disp; }},
871                     mem_flags = [], inst_flags = []) {{
872    (header_output, decoder_output, decode_block, exec_output) = \
873        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
874                      postacc_code, exec_template_base = 'StoreCond')
875}};
876