mem.isa revision 2935:d1223a6c9156
1// -*- mode:c++ -*-
2
3// Copyright (c) 2006 The Regents of The University of Michigan
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
74     /**
75     * Base class for a few miscellaneous memory-format insts
76     * that don't interpret the disp field
77     */
78    class MemoryNoDisp : public Memory
79    {
80      protected:
81        /// Constructor
82        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
83                     StaticInstPtr _eaCompPtr = nullStaticInstPtr,
84                     StaticInstPtr _memAccPtr = nullStaticInstPtr)
85            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
86        {
87        }
88
89        std::string
90        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
91    };
92}};
93
94
95output decoder {{
96    std::string
97    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
98    {
99        return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
100                        flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
101    }
102
103    std::string
104    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
105    {
106        return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
107                        flags[IsFloating] ? 'f' : 'r',
108                        flags[IsFloating] ? FD : RD,
109                        RS, RT);
110    }
111}};
112
113def template LoadStoreDeclare {{
114    /**
115     * Static instruction class for "%(mnemonic)s".
116     */
117    class %(class_name)s : public %(base_class)s
118    {
119      protected:
120
121        /**
122         * "Fake" effective address computation class for "%(mnemonic)s".
123         */
124        class EAComp : public %(base_class)s
125        {
126          public:
127            /// Constructor
128            EAComp(MachInst machInst);
129
130            %(BasicExecDeclare)s
131        };
132
133        /**
134         * "Fake" memory access instruction class for "%(mnemonic)s".
135         */
136        class MemAcc : public %(base_class)s
137        {
138          public:
139            /// Constructor
140            MemAcc(MachInst machInst);
141
142            %(BasicExecDeclare)s
143        };
144
145      public:
146
147        /// Constructor.
148        %(class_name)s(MachInst machInst);
149
150        %(BasicExecDeclare)s
151
152        %(InitiateAccDeclare)s
153
154        %(CompleteAccDeclare)s
155    };
156}};
157
158
159def template InitiateAccDeclare {{
160    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
161}};
162
163
164def template CompleteAccDeclare {{
165    Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
166}};
167
168
169def template LoadStoreConstructor {{
170    /** TODO: change op_class to AddrGenOp or something (requires
171     * creating new member of OpClass enum in op_class.hh, updating
172     * config files, etc.). */
173    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
174        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
175    {
176        %(ea_constructor)s;
177    }
178
179    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
180        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
181    {
182        %(memacc_constructor)s;
183    }
184
185    inline %(class_name)s::%(class_name)s(MachInst machInst)
186         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
187                          new EAComp(machInst), new MemAcc(machInst))
188    {
189        %(constructor)s;
190    }
191}};
192
193
194def template EACompExecute {{
195    Fault
196    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
197                                   Trace::InstRecord *traceData) const
198    {
199        Addr EA;
200        Fault fault = NoFault;
201
202        %(fp_enable_check)s;
203        %(op_decl)s;
204        %(op_rd)s;
205        %(code)s;
206
207        if (fault == NoFault) {
208            %(op_wb)s;
209            xc->setEA(EA);
210        }
211
212        return fault;
213    }
214}};
215
216def template LoadMemAccExecute {{
217    Fault
218    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
219                                   Trace::InstRecord *traceData) const
220    {
221        Addr EA;
222        Fault fault = NoFault;
223
224        %(fp_enable_check)s;
225        %(op_decl)s;
226        %(op_rd)s;
227        EA = xc->getEA();
228
229        if (fault == NoFault) {
230            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
231            %(code)s;
232        }
233
234        if (fault == NoFault) {
235            %(op_wb)s;
236        }
237
238        return fault;
239    }
240}};
241
242
243def template LoadExecute {{
244    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
245                                  Trace::InstRecord *traceData) const
246    {
247        Addr EA;
248        Fault fault = NoFault;
249
250        %(fp_enable_check)s;
251        %(op_decl)s;
252        %(op_rd)s;
253        %(ea_code)s;
254
255        if (fault == NoFault) {
256            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
257            %(memacc_code)s;
258        }
259
260        if (fault == NoFault) {
261            %(op_wb)s;
262        }
263
264        return fault;
265    }
266}};
267
268
269def template LoadInitiateAcc {{
270    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
271                                      Trace::InstRecord *traceData) const
272    {
273        Addr EA;
274        Fault fault = NoFault;
275
276        %(fp_enable_check)s;
277        %(op_src_decl)s;
278        %(op_rd)s;
279        %(ea_code)s;
280
281        if (fault == NoFault) {
282            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
283        }
284
285        return fault;
286    }
287}};
288
289
290def template LoadCompleteAcc {{
291    Fault %(class_name)s::completeAcc(Packet *pkt,
292                                      %(CPU_exec_context)s *xc,
293                                      Trace::InstRecord *traceData) const
294    {
295        Fault fault = NoFault;
296
297        %(fp_enable_check)s;
298        %(op_decl)s;
299
300        Mem = pkt->get<typeof(Mem)>();
301
302        if (fault == NoFault) {
303            %(memacc_code)s;
304        }
305
306        if (fault == NoFault) {
307            %(op_wb)s;
308        }
309
310        return fault;
311    }
312}};
313
314
315def template StoreMemAccExecute {{
316    Fault
317    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
318                                   Trace::InstRecord *traceData) const
319    {
320        Addr EA;
321        Fault fault = NoFault;
322        uint64_t write_result = 0;
323
324        %(fp_enable_check)s;
325        %(op_decl)s;
326        %(op_rd)s;
327        EA = xc->getEA();
328
329        if (fault == NoFault) {
330            %(code)s;
331        }
332
333        if (fault == NoFault) {
334            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
335                              memAccessFlags, &write_result);
336            if (traceData) { traceData->setData(Mem); }
337        }
338
339        if (fault == NoFault) {
340            %(postacc_code)s;
341        }
342
343        if (fault == NoFault) {
344            %(op_wb)s;
345        }
346
347        return fault;
348    }
349}};
350
351
352def template StoreExecute {{
353    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
354                                  Trace::InstRecord *traceData) const
355    {
356        Addr EA;
357        Fault fault = NoFault;
358        uint64_t write_result = 0;
359
360        %(fp_enable_check)s;
361        %(op_decl)s;
362        %(op_rd)s;
363        %(ea_code)s;
364
365        if (fault == NoFault) {
366            %(memacc_code)s;
367        }
368
369        if (fault == NoFault) {
370            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
371                              memAccessFlags, &write_result);
372            if (traceData) { traceData->setData(Mem); }
373        }
374
375        if (fault == NoFault) {
376            %(postacc_code)s;
377        }
378
379        if (fault == NoFault) {
380            %(op_wb)s;
381        }
382
383        return fault;
384    }
385}};
386
387def template StoreInitiateAcc {{
388    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
389                                      Trace::InstRecord *traceData) const
390    {
391        Addr EA;
392        Fault fault = NoFault;
393
394        %(fp_enable_check)s;
395        %(op_decl)s;
396        %(op_rd)s;
397        %(ea_code)s;
398
399        if (fault == NoFault) {
400            %(memacc_code)s;
401        }
402
403        if (fault == NoFault) {
404            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
405                              memAccessFlags, NULL);
406            if (traceData) { traceData->setData(Mem); }
407        }
408
409        return fault;
410    }
411}};
412
413
414def template StoreCompleteAcc {{
415    Fault %(class_name)s::completeAcc(Packet *pkt,
416                                      %(CPU_exec_context)s *xc,
417                                      Trace::InstRecord *traceData) const
418    {
419        Fault fault = NoFault;
420
421        %(fp_enable_check)s;
422        %(op_dest_decl)s;
423
424        if (fault == NoFault) {
425            %(postacc_code)s;
426        }
427
428        if (fault == NoFault) {
429            %(op_wb)s;
430        }
431
432        return fault;
433    }
434}};
435
436def template StoreCondCompleteAcc {{
437    Fault %(class_name)s::completeAcc(Packet *pkt,
438                                      %(CPU_exec_context)s *xc,
439                                      Trace::InstRecord *traceData) const
440    {
441        Fault fault = NoFault;
442
443        %(fp_enable_check)s;
444        %(op_dest_decl)s;
445
446        uint64_t write_result = pkt->req->getScResult();
447
448        if (fault == NoFault) {
449            %(postacc_code)s;
450        }
451
452        if (fault == NoFault) {
453            %(op_wb)s;
454        }
455
456        return fault;
457    }
458}};
459
460
461def template MiscMemAccExecute {{
462    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
463                                          Trace::InstRecord *traceData) const
464    {
465        Addr EA;
466        Fault fault = NoFault;
467
468        %(fp_enable_check)s;
469        %(op_decl)s;
470        %(op_rd)s;
471        EA = xc->getEA();
472
473        if (fault == NoFault) {
474            %(code)s;
475        }
476
477        return NoFault;
478    }
479}};
480
481def template MiscExecute {{
482    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
483                                  Trace::InstRecord *traceData) const
484    {
485        Addr EA;
486        Fault fault = NoFault;
487
488        %(fp_enable_check)s;
489        %(op_decl)s;
490        %(op_rd)s;
491        %(ea_code)s;
492
493        if (fault == NoFault) {
494            %(memacc_code)s;
495        }
496
497        return NoFault;
498    }
499}};
500
501def template MiscInitiateAcc {{
502    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
503                                      Trace::InstRecord *traceData) const
504    {
505        panic("Misc instruction does not support split access method!");
506        return NoFault;
507    }
508}};
509
510
511def template MiscCompleteAcc {{
512    Fault %(class_name)s::completeAcc(Packet *pkt,
513                                      %(CPU_exec_context)s *xc,
514                                      Trace::InstRecord *traceData) const
515    {
516        panic("Misc instruction does not support split access method!");
517
518        return NoFault;
519    }
520}};
521
522def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
523                     mem_flags = [], inst_flags = []) {{
524    (header_output, decoder_output, decode_block, exec_output) = \
525        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
526                      decode_template = ImmNopCheckDecode,
527                      exec_template_base = 'Load')
528}};
529
530def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
531                     mem_flags = [], inst_flags = []) {{
532    (header_output, decoder_output, decode_block, exec_output) = \
533        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
534                      exec_template_base = 'Store')
535}};
536
537def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
538                     mem_flags = [], inst_flags = []) {{
539    (header_output, decoder_output, decode_block, exec_output) = \
540        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
541                      decode_template = ImmNopCheckDecode,
542                      exec_template_base = 'Load')
543}};
544
545def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
546                     mem_flags = [], inst_flags = []) {{
547    (header_output, decoder_output, decode_block, exec_output) = \
548        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
549                      exec_template_base = 'Store')
550}};
551
552def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
553                     mem_flags = [], inst_flags = []) {{
554    decl_code = 'uint32_t mem_word = Mem.uw;\n'
555    decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
556    decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
557    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
558    decl_code += '\tbyte_offset ^= 3;\n'
559    decl_code += '#endif\n'
560
561    memacc_code = decl_code + memacc_code
562
563    (header_output, decoder_output, decode_block, exec_output) = \
564        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
565                      decode_template = ImmNopCheckDecode,
566                      exec_template_base = 'Load')
567}};
568
569def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
570                     mem_flags = [], inst_flags = []) {{
571    decl_code = 'uint32_t mem_word = 0;\n'
572    decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
573    decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
574    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
575    decl_code += '\tbyte_offset ^= 3;\n'
576    decl_code += '#endif\n'
577    decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
578    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
579
580    (header_output, decoder_output, decode_block, exec_output) = \
581        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
582                      exec_template_base = 'Store')
583}};
584
585def format Prefetch(ea_code = {{ EA = Rs + disp; }},
586                          mem_flags = [], pf_flags = [], inst_flags = []) {{
587    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
588    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
589                                  'IsDataPrefetch', 'MemReadOp']
590
591    (header_output, decoder_output, decode_block, exec_output) = \
592        LoadStoreBase(name, Name, ea_code,
593                      'xc->prefetch(EA, memAccessFlags);',
594                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
595
596}};
597
598def format StoreCond(memacc_code, postacc_code,
599                     ea_code = {{ EA = Rs + disp; }},
600                     mem_flags = [], inst_flags = []) {{
601    (header_output, decoder_output, decode_block, exec_output) = \
602        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
603                      postacc_code, exec_template_base = 'StoreCond')
604}};
605