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