mem.isa revision 12385:288c62455dde
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        /// Memory request flags.  See mem_req_base.hh.
45        Request::Flags memAccessFlags;
46
47        /// Displacement for EA calculation (signed).
48        int32_t disp;
49
50        /// Constructor
51        Memory(const char *mnem, MachInst _machInst, OpClass __opClass)
52            : MipsStaticInst(mnem, _machInst, __opClass),
53              disp(sext<16>(OFFSET))
54        {
55        }
56
57        std::string
58        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
59    };
60
61     /**
62     * Base class for a few miscellaneous memory-format insts
63     * that don't interpret the disp field
64     */
65    class MemoryNoDisp : public Memory
66    {
67      protected:
68        /// Constructor
69        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
70            : Memory(mnem, _machInst, __opClass)
71        {
72        }
73
74        std::string
75        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
76    };
77}};
78
79
80output decoder {{
81    std::string
82    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
83    {
84        return csprintf("%-10s %c%d, %d(r%d)", mnemonic,
85                        flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
86    }
87
88    std::string
89    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
90    {
91        return csprintf("%-10s %c%d, r%d(r%d)", mnemonic,
92                        flags[IsFloating] ? 'f' : 'r',
93                        flags[IsFloating] ? FD : RD,
94                        RS, RT);
95    }
96
97}};
98
99output header {{
100    uint64_t getMemData(ExecContext *xc, Packet *packet);
101
102}};
103
104output exec {{
105    /** return data in cases where there the size of data is only
106        known in the packet
107    */
108    uint64_t getMemData(ExecContext *xc, Packet *packet) {
109        switch (packet->getSize())
110        {
111          case 1:
112            return packet->get<uint8_t>();
113
114          case 2:
115            return packet->get<uint16_t>();
116
117          case 4:
118            return packet->get<uint32_t>();
119
120          case 8:
121            return packet->get<uint64_t>();
122
123          default:
124            std::cerr << "bad store data size = " << packet->getSize() << std::endl;
125
126            assert(0);
127            return 0;
128        }
129    }
130
131
132}};
133
134def template LoadStoreDeclare {{
135    /**
136     * Static instruction class for "%(mnemonic)s".
137     */
138    class %(class_name)s : public %(base_class)s
139    {
140      public:
141
142        /// Constructor.
143        %(class_name)s(ExtMachInst machInst);
144
145        Fault execute(ExecContext *, Trace::InstRecord *) const;
146        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
147        Fault completeAcc(Packet *, ExecContext *, Trace::InstRecord *) const;
148    };
149}};
150
151
152def template LoadStoreConstructor {{
153    %(class_name)s::%(class_name)s(ExtMachInst machInst)
154         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
155    {
156        %(constructor)s;
157    }
158}};
159
160def template LoadExecute {{
161    Fault %(class_name)s::execute(ExecContext *xc,
162                                  Trace::InstRecord *traceData) const
163    {
164        Addr EA;
165        Fault fault = NoFault;
166
167        if (this->isFloating()) {
168            %(fp_enable_check)s;
169
170            if(fault != NoFault)
171                return fault;
172        }
173
174        %(op_decl)s;
175        %(op_rd)s;
176        %(ea_code)s;
177
178        if (fault == NoFault) {
179            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
180            %(memacc_code)s;
181        }
182
183        if (fault == NoFault) {
184            %(op_wb)s;
185        }
186
187        return fault;
188    }
189}};
190
191
192def template LoadInitiateAcc {{
193    Fault %(class_name)s::initiateAcc(ExecContext *xc,
194                                      Trace::InstRecord *traceData) const
195    {
196        Addr EA;
197        Fault fault = NoFault;
198
199        if (this->isFloating()) {
200            %(fp_enable_check)s;
201
202            if(fault != NoFault)
203                return fault;
204        }
205
206        %(op_src_decl)s;
207        %(op_rd)s;
208        %(ea_code)s;
209
210        if (fault == NoFault) {
211            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
212        }
213
214        return fault;
215    }
216}};
217
218def template LoadCompleteAcc {{
219    Fault %(class_name)s::completeAcc(Packet *pkt, ExecContext *xc,
220                                      Trace::InstRecord *traceData) const
221    {
222        Fault fault = NoFault;
223
224        if (this->isFloating()) {
225            %(fp_enable_check)s;
226
227            if(fault != NoFault)
228                return fault;
229        }
230
231        %(op_decl)s;
232        %(op_rd)s;
233
234        getMem(pkt, Mem, traceData);
235
236        if (fault == NoFault) {
237            %(memacc_code)s;
238        }
239
240        if (fault == NoFault) {
241            %(op_wb)s;
242        }
243
244        return fault;
245    }
246}};
247
248def template StoreExecute {{
249    Fault %(class_name)s::execute(ExecContext *xc,
250                                  Trace::InstRecord *traceData) const
251    {
252        Addr EA;
253        Fault fault = NoFault;
254
255        %(fp_enable_check)s;
256        %(op_decl)s;
257        %(op_rd)s;
258        %(ea_code)s;
259
260        if (fault == NoFault) {
261            %(memacc_code)s;
262        }
263
264        if (fault == NoFault) {
265            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
266                    NULL);
267        }
268
269        if (fault == NoFault) {
270            %(postacc_code)s;
271        }
272
273        if (fault == NoFault) {
274            %(op_wb)s;
275        }
276
277        return fault;
278    }
279}};
280
281
282def template StoreFPExecute {{
283    Fault %(class_name)s::execute(ExecContext *xc,
284                                  Trace::InstRecord *traceData) const
285    {
286        Addr EA;
287        Fault fault = NoFault;
288
289        %(fp_enable_check)s;
290        if(fault != NoFault)
291          return fault;
292        %(op_decl)s;
293        %(op_rd)s;
294        %(ea_code)s;
295
296        if (fault == NoFault) {
297            %(memacc_code)s;
298        }
299
300        if (fault == NoFault) {
301            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
302                    NULL);
303        }
304
305        if (fault == NoFault) {
306            %(postacc_code)s;
307        }
308
309        if (fault == NoFault) {
310            %(op_wb)s;
311        }
312
313        return fault;
314    }
315}};
316
317def template StoreCondExecute {{
318    Fault %(class_name)s::execute(ExecContext *xc,
319                                  Trace::InstRecord *traceData) const
320    {
321        Addr EA;
322        Fault fault = NoFault;
323        uint64_t write_result = 0;
324
325        %(fp_enable_check)s;
326        %(op_decl)s;
327        %(op_rd)s;
328        %(ea_code)s;
329
330        if (fault == NoFault) {
331            %(memacc_code)s;
332        }
333
334        if (fault == NoFault) {
335            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
336                    &write_result);
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
351def template StoreInitiateAcc {{
352    Fault %(class_name)s::initiateAcc(ExecContext *xc,
353                                      Trace::InstRecord *traceData) const
354    {
355        Addr EA;
356        Fault fault = NoFault;
357
358        %(fp_enable_check)s;
359        %(op_decl)s;
360        %(op_rd)s;
361        %(ea_code)s;
362
363        if (fault == NoFault) {
364            %(memacc_code)s;
365        }
366
367        if (fault == NoFault) {
368            fault = writeMemTiming(xc, traceData, Mem, EA, memAccessFlags,
369                    NULL);
370        }
371
372        return fault;
373    }
374}};
375
376
377def template StoreCompleteAcc {{
378    Fault %(class_name)s::completeAcc(Packet *pkt,
379                                      ExecContext *xc,
380                                      Trace::InstRecord *traceData) const
381    {
382        return NoFault;
383    }
384}};
385
386def template StoreCondCompleteAcc {{
387    Fault %(class_name)s::completeAcc(Packet *pkt,
388                                      ExecContext *xc,
389                                      Trace::InstRecord *traceData) const
390    {
391        Fault fault = NoFault;
392
393        %(fp_enable_check)s;
394        %(op_dest_decl)s;
395
396        uint64_t write_result = pkt->req->getExtraData();
397
398        if (fault == NoFault) {
399            %(postacc_code)s;
400        }
401
402        if (fault == NoFault) {
403            %(op_wb)s;
404        }
405
406        return fault;
407    }
408}};
409
410def template MiscExecute {{
411    Fault %(class_name)s::execute(ExecContext *xc,
412                                  Trace::InstRecord *traceData) const
413    {
414        Addr EA M5_VAR_USED = 0;
415        Fault fault = NoFault;
416
417        %(fp_enable_check)s;
418        %(op_decl)s;
419        %(op_rd)s;
420        %(ea_code)s;
421
422        if (fault == NoFault) {
423            %(memacc_code)s;
424        }
425
426        return NoFault;
427    }
428}};
429
430def template MiscInitiateAcc {{
431    Fault %(class_name)s::initiateAcc(ExecContext *xc,
432                                      Trace::InstRecord *traceData) const
433    {
434        panic("Misc instruction does not support split access method!");
435        return NoFault;
436    }
437}};
438
439
440def template MiscCompleteAcc {{
441    Fault %(class_name)s::completeAcc(Packet *pkt, ExecContext *xc,
442                                      Trace::InstRecord *traceData) const
443    {
444        panic("Misc instruction does not support split access method!");
445
446        return NoFault;
447    }
448}};
449
450def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
451                     mem_flags = [], inst_flags = []) {{
452    (header_output, decoder_output, decode_block, exec_output) = \
453        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
454                      decode_template = ImmNopCheckDecode,
455                      exec_template_base = 'Load')
456}};
457
458
459def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
460                     mem_flags = [], inst_flags = []) {{
461    (header_output, decoder_output, decode_block, exec_output) = \
462        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
463                      exec_template_base = 'Store')
464}};
465
466def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
467                     mem_flags = [], inst_flags = []) {{
468    inst_flags += ['IsIndexed']
469    (header_output, decoder_output, decode_block, exec_output) = \
470        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
471                      decode_template = ImmNopCheckDecode,
472                      exec_template_base = 'Load')
473}};
474
475def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
476                     mem_flags = [], inst_flags = []) {{
477    inst_flags += ['IsIndexed']
478    (header_output, decoder_output, decode_block, exec_output) = \
479        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
480                      exec_template_base = 'Store')
481}};
482
483def format LoadFPIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
484                     mem_flags = [], inst_flags = []) {{
485    inst_flags += ['IsIndexed', 'IsFloating']
486    (header_output, decoder_output, decode_block, exec_output) = \
487        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
488                      decode_template = ImmNopCheckDecode,
489                      exec_template_base = 'Load')
490}};
491
492def format StoreFPIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
493                     mem_flags = [], inst_flags = []) {{
494    inst_flags += ['IsIndexed', 'IsFloating']
495    (header_output, decoder_output, decode_block, exec_output) = \
496        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
497                      exec_template_base = 'Store')
498}};
499
500
501def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
502                     mem_flags = [], inst_flags = []) {{
503    decl_code = '''
504        uint32_t mem_word = Mem_uw;
505        uint32_t unalign_addr = Rs + disp;
506        uint32_t byte_offset = unalign_addr & 3;
507        if (GuestByteOrder == BigEndianByteOrder)
508            byte_offset ^= 3;
509    '''
510
511    memacc_code = decl_code + memacc_code
512
513    (header_output, decoder_output, decode_block, exec_output) = \
514        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
515                      decode_template = ImmNopCheckDecode,
516                      exec_template_base = 'Load')
517}};
518
519def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
520                     mem_flags = [], inst_flags = []) {{
521    decl_code = '''
522        uint32_t mem_word = 0;
523        uint32_t unaligned_addr = Rs + disp;
524        uint32_t byte_offset = unaligned_addr & 3;
525        if (GuestByteOrder == BigEndianByteOrder)
526            byte_offset ^= 3;
527        fault = readMemAtomic(xc, traceData, EA, mem_word, memAccessFlags);
528    '''
529    memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
530
531    (header_output, decoder_output, decode_block, exec_output) = \
532        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
533                      exec_template_base = 'Store')
534}};
535
536def format Prefetch(ea_code = {{ EA = Rs + disp; }},
537                          mem_flags = [], pf_flags = [], inst_flags = []) {{
538    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
539    pf_inst_flags = inst_flags
540
541    (header_output, decoder_output, decode_block, exec_output) = \
542        LoadStoreBase(name, Name, ea_code,
543                      'warn_once("Prefetching not implemented for MIPS\\n");',
544                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
545
546}};
547
548def format StoreCond(memacc_code, postacc_code,
549                     ea_code = {{ EA = Rs + disp; }},
550                     mem_flags = [], inst_flags = []) {{
551    (header_output, decoder_output, decode_block, exec_output) = \
552        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
553                      postacc_code, exec_template_base = 'StoreCond')
554}};
555