mem.isa revision 2750
1// -*- mode:c++ -*-
2
3// Copyright (c) 2003-2005 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: Gabe Black
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(uint8_t *, %(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(uint8_t *data,
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        memcpy(&Mem, data, sizeof(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        uint64_t write_result = 0;
394
395        %(fp_enable_check)s;
396        %(op_decl)s;
397        %(op_rd)s;
398        %(ea_code)s;
399
400        if (fault == NoFault) {
401            %(memacc_code)s;
402        }
403
404        if (fault == NoFault) {
405            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
406                              memAccessFlags, &write_result);
407            if (traceData) { traceData->setData(Mem); }
408        }
409
410        return fault;
411    }
412}};
413
414
415def template StoreCompleteAcc {{
416    Fault %(class_name)s::completeAcc(uint8_t *data,
417                                      %(CPU_exec_context)s *xc,
418                                      Trace::InstRecord *traceData) const
419    {
420        Fault fault = NoFault;
421        uint64_t write_result = 0;
422
423        %(fp_enable_check)s;
424        %(op_dest_decl)s;
425
426        memcpy(&write_result, data, sizeof(write_result));
427
428        if (fault == NoFault) {
429            %(postacc_code)s;
430        }
431
432        if (fault == NoFault) {
433            %(op_wb)s;
434        }
435
436        return fault;
437    }
438}};
439
440
441def template MiscMemAccExecute {{
442    Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
443                                          Trace::InstRecord *traceData) const
444    {
445        Addr EA;
446        Fault fault = NoFault;
447
448        %(fp_enable_check)s;
449        %(op_decl)s;
450        %(op_rd)s;
451        EA = xc->getEA();
452
453        if (fault == NoFault) {
454            %(code)s;
455        }
456
457        return NoFault;
458    }
459}};
460
461def template MiscExecute {{
462    Fault %(class_name)s::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_code)s;
472
473        if (fault == NoFault) {
474            %(memacc_code)s;
475        }
476
477        return NoFault;
478    }
479}};
480
481def template MiscInitiateAcc {{
482    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
483                                      Trace::InstRecord *traceData) const
484    {
485        panic("Misc instruction does not support split access method!");
486        return NoFault;
487    }
488}};
489
490
491def template MiscCompleteAcc {{
492    Fault %(class_name)s::completeAcc(uint8_t *data,
493                                      %(CPU_exec_context)s *xc,
494                                      Trace::InstRecord *traceData) const
495    {
496        panic("Misc instruction does not support split access method!");
497
498        return NoFault;
499    }
500}};
501
502def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
503                     mem_flags = [], inst_flags = []) {{
504    (header_output, decoder_output, decode_block, exec_output) = \
505        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
506                      decode_template = ImmNopCheckDecode,
507                      exec_template_base = 'Load')
508}};
509
510def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
511                     mem_flags = [], inst_flags = []) {{
512    (header_output, decoder_output, decode_block, exec_output) = \
513        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
514                      exec_template_base = 'Store')
515}};
516
517def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
518                     mem_flags = [], inst_flags = []) {{
519    (header_output, decoder_output, decode_block, exec_output) = \
520        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
521                      decode_template = ImmNopCheckDecode,
522                      exec_template_base = 'Load')
523}};
524
525def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
526                     mem_flags = [], inst_flags = []) {{
527    (header_output, decoder_output, decode_block, exec_output) = \
528        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
529                      exec_template_base = 'Store')
530}};
531
532def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
533                     mem_flags = [], inst_flags = []) {{
534    decl_code = 'uint32_t mem_word = Mem.uw;\n'
535    decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
536    decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
537    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
538    decl_code += '\tbyte_offset ^= 3;\n'
539    decl_code += '#endif\n'
540
541    memacc_code = decl_code + memacc_code
542
543    (header_output, decoder_output, decode_block, exec_output) = \
544        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
545                      decode_template = ImmNopCheckDecode,
546                      exec_template_base = 'Load')
547}};
548
549def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
550                     mem_flags = [], inst_flags = []) {{
551    decl_code = 'uint32_t mem_word = 0;\n'
552    decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
553    decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
554    decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
555    decl_code += '\tbyte_offset ^= 3;\n'
556    decl_code += '#endif\n'
557    decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
558    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
559
560    (header_output, decoder_output, decode_block, exec_output) = \
561        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
562                      exec_template_base = 'Store')
563}};
564
565def format Prefetch(ea_code = {{ EA = Rs + disp; }},
566                          mem_flags = [], pf_flags = [], inst_flags = []) {{
567    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
568    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
569                                  'IsDataPrefetch', 'MemReadOp']
570
571    (header_output, decoder_output, decode_block, exec_output) = \
572        LoadStoreBase(name, Name, ea_code,
573                      'xc->prefetch(EA, memAccessFlags);',
574                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
575
576}};
577
578def format StoreCond(memacc_code, postacc_code,
579                     ea_code = {{ EA = Rs + disp; }},
580                     mem_flags = [], inst_flags = []) {{
581    (header_output, decoder_output, decode_block, exec_output) = \
582        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
583                      postacc_code, exec_template_base = 'Store')
584}};
585