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