mem.isa revision 2132
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
29output header {{
30    /**
31     * Base class for general Mips memory-format instructions.
32     */
33    class Memory : public MipsStaticInst
34    {
35      protected:
36
37        /// Memory request flags.  See mem_req_base.hh.
38        unsigned memAccessFlags;
39        /// Pointer to EAComp object.
40        const StaticInstPtr eaCompPtr;
41        /// Pointer to MemAcc object.
42        const StaticInstPtr memAccPtr;
43        /// Displacement for EA calculation (signed).
44        int32_t disp;
45
46        /// Constructor
47        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
48               StaticInstPtr _eaCompPtr = nullStaticInstPtr,
49               StaticInstPtr _memAccPtr = nullStaticInstPtr)
50            : MipsStaticInst(mnem, _machInst, __opClass),
51              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
52              disp(OFFSET)
53        {
54        }
55
56        std::string
57        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
58
59      public:
60
61        const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
62        const StaticInstPtr &memAccInst() const { return memAccPtr; }
63    };
64
65}};
66
67
68output decoder {{
69    std::string
70    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
71    {
72        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
73                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
74    }
75
76}};
77
78def format LoadAddress(code) {{
79    iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
80    header_output = BasicDeclare.subst(iop)
81    decoder_output = BasicConstructor.subst(iop)
82    decode_block = BasicDecode.subst(iop)
83    exec_output = BasicExecute.subst(iop)
84}};
85
86
87def template LoadStoreDeclare {{
88    /**
89     * Static instruction class for "%(mnemonic)s".
90     */
91    class %(class_name)s : public %(base_class)s
92    {
93      protected:
94
95        /**
96         * "Fake" effective address computation class for "%(mnemonic)s".
97         */
98        class EAComp : public %(base_class)s
99        {
100          public:
101            /// Constructor
102            EAComp(MachInst machInst);
103
104            %(BasicExecDeclare)s
105        };
106
107        /**
108         * "Fake" memory access instruction class for "%(mnemonic)s".
109         */
110        class MemAcc : public %(base_class)s
111        {
112          public:
113            /// Constructor
114            MemAcc(MachInst machInst);
115
116            %(BasicExecDeclare)s
117        };
118
119      public:
120
121        /// Constructor.
122        %(class_name)s(MachInst machInst);
123
124        %(BasicExecDeclare)s
125
126        %(InitiateAccDeclare)s
127
128        %(CompleteAccDeclare)s
129    };
130}};
131
132
133def template InitiateAccDeclare {{
134    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
135}};
136
137
138def template CompleteAccDeclare {{
139    Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
140}};
141
142
143def template LoadStoreConstructor {{
144    /** TODO: change op_class to AddrGenOp or something (requires
145     * creating new member of OpClass enum in op_class.hh, updating
146     * config files, etc.). */
147    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
148        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
149    {
150        %(ea_constructor)s;
151    }
152
153    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
154        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
155    {
156        %(memacc_constructor)s;
157    }
158
159    inline %(class_name)s::%(class_name)s(MachInst machInst)
160         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
161                          new EAComp(machInst), new MemAcc(machInst))
162    {
163        %(constructor)s;
164    }
165}};
166
167
168def template EACompExecute {{
169    Fault
170    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
171                                   Trace::InstRecord *traceData) const
172    {
173        Addr EA;
174        Fault fault = NoFault;
175
176        %(fp_enable_check)s;
177        %(op_decl)s;
178        %(op_rd)s;
179        %(code)s;
180
181        if (fault == NoFault) {
182            %(op_wb)s;
183            xc->setEA(EA);
184        }
185
186        return fault;
187    }
188}};
189
190def template LoadMemAccExecute {{
191    Fault
192    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
193                                   Trace::InstRecord *traceData) const
194    {
195        Addr EA;
196        Fault fault = NoFault;
197
198        %(fp_enable_check)s;
199        %(op_decl)s;
200        %(op_rd)s;
201        EA = xc->getEA();
202
203        if (fault == NoFault) {
204            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
205            %(code)s;
206        }
207
208        if (fault == NoFault) {
209            %(op_wb)s;
210        }
211
212        return fault;
213    }
214}};
215
216
217def template LoadExecute {{
218    Fault %(class_name)s::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_code)s;
228
229        if (fault == NoFault) {
230            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
231            %(memacc_code)s;
232        }
233
234        if (fault == NoFault) {
235            %(op_wb)s;
236        }
237
238        return fault;
239    }
240}};
241
242
243def template LoadInitiateAcc {{
244    Fault %(class_name)s::initiateAcc(%(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_src_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        }
258
259        return fault;
260    }
261}};
262
263
264def template LoadCompleteAcc {{
265    Fault %(class_name)s::completeAcc(uint8_t *data,
266                                      %(CPU_exec_context)s *xc,
267                                      Trace::InstRecord *traceData) const
268    {
269        Fault fault = NoFault;
270
271        %(fp_enable_check)s;
272        %(op_src_decl)s;
273        %(op_dest_decl)s;
274
275        memcpy(&Mem, data, sizeof(Mem));
276
277        if (fault == NoFault) {
278            %(memacc_code)s;
279        }
280
281        if (fault == NoFault) {
282            %(op_wb)s;
283        }
284
285        return fault;
286    }
287}};
288
289
290def template StoreMemAccExecute {{
291    Fault
292    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
293                                   Trace::InstRecord *traceData) const
294    {
295        Addr EA;
296        Fault fault = NoFault;
297        uint64_t write_result = 0;
298
299        %(fp_enable_check)s;
300        %(op_decl)s;
301        %(op_rd)s;
302        EA = xc->getEA();
303
304        if (fault == NoFault) {
305            %(code)s;
306        }
307
308        if (fault == NoFault) {
309            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
310                              memAccessFlags, &write_result);
311            if (traceData) { traceData->setData(Mem); }
312        }
313
314        if (fault == NoFault) {
315            %(postacc_code)s;
316        }
317
318        if (fault == NoFault) {
319            %(op_wb)s;
320        }
321
322        return fault;
323    }
324}};
325
326
327def template StoreExecute {{
328    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
329                                  Trace::InstRecord *traceData) const
330    {
331        Addr EA;
332        Fault fault = NoFault;
333        uint64_t write_result = 0;
334
335        %(fp_enable_check)s;
336        %(op_decl)s;
337        %(op_rd)s;
338        %(ea_code)s;
339
340        if (fault == NoFault) {
341            %(memacc_code)s;
342        }
343
344        if (fault == NoFault) {
345            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
346                              memAccessFlags, &write_result);
347            if (traceData) { traceData->setData(Mem); }
348        }
349
350        if (fault == NoFault) {
351            %(postacc_code)s;
352        }
353
354        if (fault == NoFault) {
355            %(op_wb)s;
356        }
357
358        return fault;
359    }
360}};
361
362def template StoreInitiateAcc {{
363    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
364                                      Trace::InstRecord *traceData) const
365    {
366        Addr EA;
367        Fault fault = NoFault;
368        uint64_t write_result = 0;
369
370        %(fp_enable_check)s;
371        %(op_src_decl)s;
372        %(op_dest_decl)s;
373        %(op_rd)s;
374        %(ea_code)s;
375
376        if (fault == NoFault) {
377            %(memacc_code)s;
378        }
379
380        if (fault == NoFault) {
381            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
382                              memAccessFlags, &write_result);
383            if (traceData) { traceData->setData(Mem); }
384        }
385
386        return fault;
387    }
388}};
389
390
391def template StoreCompleteAcc {{
392    Fault %(class_name)s::completeAcc(uint8_t *data,
393                                      %(CPU_exec_context)s *xc,
394                                      Trace::InstRecord *traceData) const
395    {
396        Fault fault = NoFault;
397        uint64_t write_result = 0;
398
399        %(fp_enable_check)s;
400        %(op_dest_decl)s;
401
402        memcpy(&write_result, data, sizeof(write_result));
403
404        if (fault == NoFault) {
405            %(postacc_code)s;
406        }
407
408        if (fault == NoFault) {
409            %(op_wb)s;
410        }
411
412        return fault;
413    }
414}};
415
416// load instructions use Rt as dest, so check for
417// Rt == 31 to detect nops
418def template LoadNopCheckDecode {{
419 {
420     MipsStaticInst *i = new %(class_name)s(machInst);
421     if (RT == 0) {
422         i = makeNop(i);
423     }
424     return i;
425 }
426}};
427
428def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
429                     mem_flags = [], inst_flags = []) {{
430    (header_output, decoder_output, decode_block, exec_output) = \
431        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
432                      decode_template = LoadNopCheckDecode,
433                      exec_template_base = 'Load')
434}};
435
436
437def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
438                     mem_flags = [], inst_flags = []) {{
439    (header_output, decoder_output, decode_block, exec_output) = \
440        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
441                      exec_template_base = 'Store')
442}};
443
444//FP loads are offloaded to these formats for now ...
445def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }},
446                      mem_flags = [], inst_flags = []) {{
447    (header_output, decoder_output, decode_block, exec_output) = \
448        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
449                      decode_template = LoadNopCheckDecode,
450                      exec_template_base = 'Load')
451}};
452
453
454//FP stores are offloaded to these formats for now ...
455def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }},
456                      mem_flags = [], inst_flags = []) {{
457    (header_output, decoder_output, decode_block, exec_output) = \
458        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
459                      decode_template = LoadNopCheckDecode,
460                      exec_template_base = 'Store')
461}};
462
463