mem.isa revision 6739:48d10ba361c9
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: Steve Reinhardt
30//          Kevin Lim
31
32////////////////////////////////////////////////////////////////////
33//
34// Memory-format instructions: LoadAddress, Load, Store
35//
36
37output header {{
38    /**
39     * Base class for general Alpha memory-format instructions.
40     */
41    class Memory : public AlphaStaticInst
42    {
43      protected:
44
45        /// Memory request flags.  See mem_req_base.hh.
46        Request::Flags memAccessFlags;
47
48        /// Constructor
49        Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
50            : AlphaStaticInst(mnem, _machInst, __opClass)
51        {
52        }
53
54        std::string
55        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
56    };
57
58    /**
59     * Base class for memory-format instructions using a 32-bit
60     * displacement (i.e. most of them).
61     */
62    class MemoryDisp32 : public Memory
63    {
64      protected:
65        /// Displacement for EA calculation (signed).
66        int32_t disp;
67
68        /// Constructor.
69        MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
70            : Memory(mnem, _machInst, __opClass),
71              disp(MEMDISP)
72        {
73        }
74    };
75
76
77    /**
78     * Base class for a few miscellaneous memory-format insts
79     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
80     * None of these instructions has a destination register either.
81     */
82    class MemoryNoDisp : public Memory
83    {
84      protected:
85        /// Constructor
86        MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
87            : Memory(mnem, _machInst, __opClass)
88        {
89        }
90
91        std::string
92        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
93    };
94}};
95
96
97output decoder {{
98    std::string
99    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
100    {
101        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
102                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
103    }
104
105    std::string
106    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
107    {
108        return csprintf("%-10s (r%d)", mnemonic, RB);
109    }
110}};
111
112def format LoadAddress(code) {{
113    iop = InstObjParams(name, Name, 'MemoryDisp32', code)
114    header_output = BasicDeclare.subst(iop)
115    decoder_output = BasicConstructor.subst(iop)
116    decode_block = BasicDecode.subst(iop)
117    exec_output = BasicExecute.subst(iop)
118}};
119
120
121def template LoadStoreDeclare {{
122    /**
123     * Static instruction class for "%(mnemonic)s".
124     */
125    class %(class_name)s : public %(base_class)s
126    {
127      public:
128
129        /// Constructor.
130        %(class_name)s(ExtMachInst machInst);
131
132        %(BasicExecDeclare)s
133
134        %(EACompDeclare)s
135
136        %(InitiateAccDeclare)s
137
138        %(CompleteAccDeclare)s
139    };
140}};
141
142
143def template EACompDeclare {{
144    Fault eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
145}};
146
147def template InitiateAccDeclare {{
148    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
149}};
150
151
152def template CompleteAccDeclare {{
153    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
154                      Trace::InstRecord *) const;
155}};
156
157def template LoadStoreConstructor {{
158    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
159         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
160    {
161        %(constructor)s;
162    }
163}};
164
165def template EACompExecute {{
166    Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
167                                  Trace::InstRecord *traceData) const
168    {
169        Addr EA;
170        Fault fault = NoFault;
171
172        %(fp_enable_check)s;
173        %(op_decl)s;
174        %(op_rd)s;
175        %(ea_code)s;
176
177        if (fault == NoFault) {
178            %(op_wb)s;
179            xc->setEA(EA);
180        }
181
182        return fault;
183    }
184}};
185
186
187def template LoadExecute {{
188    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
189                                  Trace::InstRecord *traceData) const
190    {
191        Addr EA;
192        Fault fault = NoFault;
193
194        %(fp_enable_check)s;
195        %(op_decl)s;
196        %(op_rd)s;
197        %(ea_code)s;
198
199        if (fault == NoFault) {
200            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
201            %(memacc_code)s;
202        }
203
204        if (fault == NoFault) {
205            %(op_wb)s;
206        }
207
208        return fault;
209    }
210}};
211
212
213def template LoadInitiateAcc {{
214    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
215                                      Trace::InstRecord *traceData) const
216    {
217        Addr EA;
218        Fault fault = NoFault;
219
220        %(fp_enable_check)s;
221        %(op_src_decl)s;
222        %(op_rd)s;
223        %(ea_code)s;
224
225        if (fault == NoFault) {
226            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
227        }
228
229        return fault;
230    }
231}};
232
233
234def template LoadCompleteAcc {{
235    Fault %(class_name)s::completeAcc(PacketPtr pkt,
236                                      %(CPU_exec_context)s *xc,
237                                      Trace::InstRecord *traceData) const
238    {
239        Fault fault = NoFault;
240
241        %(fp_enable_check)s;
242        %(op_decl)s;
243
244        Mem = pkt->get<typeof(Mem)>();
245
246        if (fault == NoFault) {
247            %(memacc_code)s;
248        }
249
250        if (fault == NoFault) {
251            %(op_wb)s;
252        }
253
254        return fault;
255    }
256}};
257
258
259def template StoreExecute {{
260    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
261                                  Trace::InstRecord *traceData) const
262    {
263        Addr EA;
264        Fault fault = NoFault;
265
266        %(fp_enable_check)s;
267        %(op_decl)s;
268        %(op_rd)s;
269        %(ea_code)s;
270
271        if (fault == NoFault) {
272            %(memacc_code)s;
273        }
274
275        if (fault == NoFault) {
276            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
277                              memAccessFlags, NULL);
278            if (traceData) { traceData->setData(Mem); }
279        }
280
281        if (fault == NoFault) {
282            %(postacc_code)s;
283        }
284
285        if (fault == NoFault) {
286            %(op_wb)s;
287        }
288
289        return fault;
290    }
291}};
292
293def template StoreCondExecute {{
294    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
295                                  Trace::InstRecord *traceData) const
296    {
297        Addr EA;
298        Fault fault = NoFault;
299        uint64_t write_result = 0;
300
301        %(fp_enable_check)s;
302        %(op_decl)s;
303        %(op_rd)s;
304        %(ea_code)s;
305
306        if (fault == NoFault) {
307            %(memacc_code)s;
308        }
309
310        if (fault == NoFault) {
311            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
312                              memAccessFlags, &write_result);
313            if (traceData) { traceData->setData(Mem); }
314        }
315
316        if (fault == NoFault) {
317            %(postacc_code)s;
318        }
319
320        if (fault == NoFault) {
321            %(op_wb)s;
322        }
323
324        return fault;
325    }
326}};
327
328def template StoreInitiateAcc {{
329    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
330                                      Trace::InstRecord *traceData) const
331    {
332        Addr EA;
333        Fault fault = NoFault;
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, NULL);
347            if (traceData) { traceData->setData(Mem); }
348        }
349
350        return fault;
351    }
352}};
353
354
355def template StoreCompleteAcc {{
356    Fault %(class_name)s::completeAcc(PacketPtr pkt,
357                                      %(CPU_exec_context)s *xc,
358                                      Trace::InstRecord *traceData) const
359    {
360        Fault fault = NoFault;
361
362        %(fp_enable_check)s;
363        %(op_dest_decl)s;
364
365        if (fault == NoFault) {
366            %(postacc_code)s;
367        }
368
369        if (fault == NoFault) {
370            %(op_wb)s;
371        }
372
373        return fault;
374    }
375}};
376
377
378def template StoreCondCompleteAcc {{
379    Fault %(class_name)s::completeAcc(PacketPtr pkt,
380                                      %(CPU_exec_context)s *xc,
381                                      Trace::InstRecord *traceData) const
382    {
383        Fault fault = NoFault;
384
385        %(fp_enable_check)s;
386        %(op_dest_decl)s;
387
388        uint64_t write_result = pkt->req->getExtraData();
389
390        if (fault == NoFault) {
391            %(postacc_code)s;
392        }
393
394        if (fault == NoFault) {
395            %(op_wb)s;
396        }
397
398        return fault;
399    }
400}};
401
402
403def template MiscExecute {{
404    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
405                                  Trace::InstRecord *traceData) const
406    {
407        Addr EA;
408        Fault fault = NoFault;
409
410        %(fp_enable_check)s;
411        %(op_decl)s;
412        %(op_rd)s;
413        %(ea_code)s;
414
415        if (fault == NoFault) {
416            %(memacc_code)s;
417        }
418
419        return NoFault;
420    }
421}};
422
423def template MiscInitiateAcc {{
424    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
425                                      Trace::InstRecord *traceData) const
426    {
427        warn("initiateAcc undefined: Misc instruction does not support split "
428             "access method!");
429        return NoFault;
430    }
431}};
432
433
434def template MiscCompleteAcc {{
435    Fault %(class_name)s::completeAcc(PacketPtr pkt,
436                                      %(CPU_exec_context)s *xc,
437                                      Trace::InstRecord *traceData) const
438    {
439        warn("completeAcc undefined: Misc instruction does not support split "
440             "access method!");
441
442        return NoFault;
443    }
444}};
445
446
447// load instructions use Ra as dest, so check for
448// Ra == 31 to detect nops
449def template LoadNopCheckDecode {{
450 {
451     AlphaStaticInst *i = new %(class_name)s(machInst);
452     if (RA == 31) {
453         i = makeNop(i);
454     }
455     return i;
456 }
457}};
458
459
460// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
461def template LoadPrefetchCheckDecode {{
462 {
463     if (RA != 31) {
464         return new %(class_name)s(machInst);
465     }
466     else {
467         return new %(class_name)sPrefetch(machInst);
468     }
469 }
470}};
471
472
473let {{
474def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
475                  postacc_code = '', base_class = 'MemoryDisp32',
476                  decode_template = BasicDecode, exec_template_base = ''):
477    # Make sure flags are in lists (convert to lists if not).
478    mem_flags = makeList(mem_flags)
479    inst_flags = makeList(inst_flags)
480
481    # add hook to get effective addresses into execution trace output.
482    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
483
484    # Some CPU models execute the memory operation as an atomic unit,
485    # while others want to separate them into an effective address
486    # computation and a memory access operation.  As a result, we need
487    # to generate three StaticInst objects.  Note that the latter two
488    # are nested inside the larger "atomic" one.
489
490    # Generate InstObjParams for each of the three objects.  Note that
491    # they differ only in the set of code objects contained (which in
492    # turn affects the object's overall operand list).
493    iop = InstObjParams(name, Name, base_class,
494                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
495                        inst_flags)
496    memacc_iop = InstObjParams(name, Name, base_class,
497                        { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
498                        inst_flags)
499
500    if mem_flags:
501        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
502        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
503        iop.constructor += s
504        memacc_iop.constructor += s
505
506    # select templates
507
508    # The InitiateAcc template is the same for StoreCond templates as the
509    # corresponding Store template..
510    StoreCondInitiateAcc = StoreInitiateAcc
511
512    fullExecTemplate = eval(exec_template_base + 'Execute')
513    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
514    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
515
516    # (header_output, decoder_output, decode_block, exec_output)
517    return (LoadStoreDeclare.subst(iop),
518            LoadStoreConstructor.subst(iop),
519            decode_template.subst(iop),
520            fullExecTemplate.subst(iop)
521            + EACompExecute.subst(iop)
522            + initiateAccTemplate.subst(iop)
523            + completeAccTemplate.subst(iop))
524}};
525
526def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
527                     mem_flags = [], inst_flags = []) {{
528    (header_output, decoder_output, decode_block, exec_output) = \
529        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
530                      decode_template = LoadNopCheckDecode,
531                      exec_template_base = 'Load')
532}};
533
534
535// Note that the flags passed in apply only to the prefetch version
536def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
537                          mem_flags = [], pf_flags = [], inst_flags = []) {{
538    # declare the load instruction object and generate the decode block
539    (header_output, decoder_output, decode_block, exec_output) = \
540        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
541                      decode_template = LoadPrefetchCheckDecode,
542                      exec_template_base = 'Load')
543
544    # Declare the prefetch instruction object.
545
546    # Make sure flag args are lists so we can mess with them.
547    mem_flags = makeList(mem_flags)
548    pf_flags = makeList(pf_flags)
549    inst_flags = makeList(inst_flags)
550
551    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
552    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
553                                  'IsDataPrefetch', 'MemReadOp']
554
555    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
556        LoadStoreBase(name, Name + 'Prefetch', ea_code,
557                      'xc->prefetch(EA, memAccessFlags);',
558                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
559
560    header_output += pf_header_output
561    decoder_output += pf_decoder_output
562    exec_output += pf_exec_output
563}};
564
565
566def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
567                 mem_flags = [], inst_flags = []) {{
568    (header_output, decoder_output, decode_block, exec_output) = \
569        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
570                      exec_template_base = 'Store')
571}};
572
573
574def format StoreCond(memacc_code, postacc_code,
575                     ea_code = {{ EA = Rb + disp; }},
576                     mem_flags = [], inst_flags = []) {{
577    (header_output, decoder_output, decode_block, exec_output) = \
578        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
579                      postacc_code, exec_template_base = 'StoreCond')
580}};
581
582
583// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
584def format MiscPrefetch(ea_code, memacc_code,
585                        mem_flags = [], inst_flags = []) {{
586    (header_output, decoder_output, decode_block, exec_output) = \
587        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
588                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
589}};
590
591
592