mem.isa revision 2124
18926Sandreas.hansson@arm.com// -*- mode:c++ -*-
28926Sandreas.hansson@arm.com
38926Sandreas.hansson@arm.com// Copyright (c) 2003-2005 The Regents of The University of Michigan
48926Sandreas.hansson@arm.com// All rights reserved.
58926Sandreas.hansson@arm.com//
68926Sandreas.hansson@arm.com// Redistribution and use in source and binary forms, with or without
78926Sandreas.hansson@arm.com// modification, are permitted provided that the following conditions are
88926Sandreas.hansson@arm.com// met: redistributions of source code must retain the above copyright
98926Sandreas.hansson@arm.com// notice, this list of conditions and the following disclaimer;
108926Sandreas.hansson@arm.com// redistributions in binary form must reproduce the above copyright
118926Sandreas.hansson@arm.com// notice, this list of conditions and the following disclaimer in the
128926Sandreas.hansson@arm.com// documentation and/or other materials provided with the distribution;
134486Sbinkertn@umich.edu// neither the name of the copyright holders nor the names of its
144486Sbinkertn@umich.edu// contributors may be used to endorse or promote products derived from
154486Sbinkertn@umich.edu// this software without specific prior written permission.
164486Sbinkertn@umich.edu//
174486Sbinkertn@umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184486Sbinkertn@umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194486Sbinkertn@umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
204486Sbinkertn@umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
214486Sbinkertn@umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
224486Sbinkertn@umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
234486Sbinkertn@umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
244486Sbinkertn@umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
254486Sbinkertn@umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
264486Sbinkertn@umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
274486Sbinkertn@umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284486Sbinkertn@umich.edu
294486Sbinkertn@umich.eduoutput header {{
304486Sbinkertn@umich.edu    /**
314486Sbinkertn@umich.edu     * Base class for general Mips memory-format instructions.
324486Sbinkertn@umich.edu     */
334486Sbinkertn@umich.edu    class Memory : public MipsStaticInst
344486Sbinkertn@umich.edu    {
354486Sbinkertn@umich.edu      protected:
364486Sbinkertn@umich.edu
374486Sbinkertn@umich.edu        /// Memory request flags.  See mem_req_base.hh.
384486Sbinkertn@umich.edu        unsigned memAccessFlags;
394486Sbinkertn@umich.edu        /// Pointer to EAComp object.
404486Sbinkertn@umich.edu        const StaticInstPtr eaCompPtr;
414486Sbinkertn@umich.edu        /// Pointer to MemAcc object.
425529Snate@binkert.org        const StaticInstPtr memAccPtr;
4310381Sdam.sunwoo@arm.com        /// Displacement for EA calculation (signed).
444486Sbinkertn@umich.edu        int32_t disp;
455529Snate@binkert.org
469518SAndreas.Sandberg@ARM.com        /// Constructor
479518SAndreas.Sandberg@ARM.com        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
489518SAndreas.Sandberg@ARM.com               StaticInstPtr _eaCompPtr = nullStaticInstPtr,
499518SAndreas.Sandberg@ARM.com               StaticInstPtr _memAccPtr = nullStaticInstPtr)
504486Sbinkertn@umich.edu            : MipsStaticInst(mnem, _machInst, __opClass),
519338SAndreas.Sandberg@arm.com              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
529518SAndreas.Sandberg@ARM.com              disp(OFFSET)
539518SAndreas.Sandberg@ARM.com        {
549518SAndreas.Sandberg@ARM.com        }
559518SAndreas.Sandberg@ARM.com
569518SAndreas.Sandberg@ARM.com        std::string
579518SAndreas.Sandberg@ARM.com        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
589518SAndreas.Sandberg@ARM.com
599518SAndreas.Sandberg@ARM.com      public:
609518SAndreas.Sandberg@ARM.com
614486Sbinkertn@umich.edu        const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
625487Snate@binkert.org        const StaticInstPtr &memAccInst() const { return memAccPtr; }
635487Snate@binkert.org    };
648926Sandreas.hansson@arm.com
6510381Sdam.sunwoo@arm.com}};
6610381Sdam.sunwoo@arm.com
6710381Sdam.sunwoo@arm.com
6810381Sdam.sunwoo@arm.comoutput decoder {{
6910381Sdam.sunwoo@arm.com    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