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