mem.isa revision 7045:e21fe6a62b1c
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        }
279
280        if (fault == NoFault) {
281            %(postacc_code)s;
282        }
283
284        if (fault == NoFault) {
285            %(op_wb)s;
286        }
287
288        return fault;
289    }
290}};
291
292def template StoreCondExecute {{
293    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
294                                  Trace::InstRecord *traceData) const
295    {
296        Addr EA;
297        Fault fault = NoFault;
298        uint64_t write_result = 0;
299
300        %(fp_enable_check)s;
301        %(op_decl)s;
302        %(op_rd)s;
303        %(ea_code)s;
304
305        if (fault == NoFault) {
306            %(memacc_code)s;
307        }
308
309        if (fault == NoFault) {
310            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
311                              memAccessFlags, &write_result);
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
326def template StoreInitiateAcc {{
327    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
328                                      Trace::InstRecord *traceData) const
329    {
330        Addr EA;
331        Fault fault = NoFault;
332
333        %(fp_enable_check)s;
334        %(op_decl)s;
335        %(op_rd)s;
336        %(ea_code)s;
337
338        if (fault == NoFault) {
339            %(memacc_code)s;
340        }
341
342        if (fault == NoFault) {
343            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
344                              memAccessFlags, NULL);
345        }
346
347        return fault;
348    }
349}};
350
351
352def template StoreCompleteAcc {{
353    Fault %(class_name)s::completeAcc(PacketPtr pkt,
354                                      %(CPU_exec_context)s *xc,
355                                      Trace::InstRecord *traceData) const
356    {
357        Fault fault = NoFault;
358
359        %(fp_enable_check)s;
360        %(op_dest_decl)s;
361
362        if (fault == NoFault) {
363            %(postacc_code)s;
364        }
365
366        if (fault == NoFault) {
367            %(op_wb)s;
368        }
369
370        return fault;
371    }
372}};
373
374
375def template StoreCondCompleteAcc {{
376    Fault %(class_name)s::completeAcc(PacketPtr pkt,
377                                      %(CPU_exec_context)s *xc,
378                                      Trace::InstRecord *traceData) const
379    {
380        Fault fault = NoFault;
381
382        %(fp_enable_check)s;
383        %(op_dest_decl)s;
384
385        uint64_t write_result = pkt->req->getExtraData();
386
387        if (fault == NoFault) {
388            %(postacc_code)s;
389        }
390
391        if (fault == NoFault) {
392            %(op_wb)s;
393        }
394
395        return fault;
396    }
397}};
398
399
400def template MiscExecute {{
401    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
402                                  Trace::InstRecord *traceData) const
403    {
404        Addr EA;
405        Fault fault = NoFault;
406
407        %(fp_enable_check)s;
408        %(op_decl)s;
409        %(op_rd)s;
410        %(ea_code)s;
411
412        if (fault == NoFault) {
413            %(memacc_code)s;
414        }
415
416        return NoFault;
417    }
418}};
419
420def template MiscInitiateAcc {{
421    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
422                                      Trace::InstRecord *traceData) const
423    {
424        warn("initiateAcc undefined: Misc instruction does not support split "
425             "access method!");
426        return NoFault;
427    }
428}};
429
430
431def template MiscCompleteAcc {{
432    Fault %(class_name)s::completeAcc(PacketPtr pkt,
433                                      %(CPU_exec_context)s *xc,
434                                      Trace::InstRecord *traceData) const
435    {
436        warn("completeAcc undefined: Misc instruction does not support split "
437             "access method!");
438
439        return NoFault;
440    }
441}};
442
443
444// load instructions use Ra as dest, so check for
445// Ra == 31 to detect nops
446def template LoadNopCheckDecode {{
447 {
448     AlphaStaticInst *i = new %(class_name)s(machInst);
449     if (RA == 31) {
450         i = makeNop(i);
451     }
452     return i;
453 }
454}};
455
456
457// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
458def template LoadPrefetchCheckDecode {{
459 {
460     if (RA != 31) {
461         return new %(class_name)s(machInst);
462     }
463     else {
464         return new %(class_name)sPrefetch(machInst);
465     }
466 }
467}};
468
469
470let {{
471def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
472                  postacc_code = '', base_class = 'MemoryDisp32',
473                  decode_template = BasicDecode, exec_template_base = ''):
474    # Make sure flags are in lists (convert to lists if not).
475    mem_flags = makeList(mem_flags)
476    inst_flags = makeList(inst_flags)
477
478    # Some CPU models execute the memory operation as an atomic unit,
479    # while others want to separate them into an effective address
480    # computation and a memory access operation.  As a result, we need
481    # to generate three StaticInst objects.  Note that the latter two
482    # are nested inside the larger "atomic" one.
483
484    # Generate InstObjParams for each of the three objects.  Note that
485    # they differ only in the set of code objects contained (which in
486    # turn affects the object's overall operand list).
487    iop = InstObjParams(name, Name, base_class,
488                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
489                        inst_flags)
490    memacc_iop = InstObjParams(name, Name, base_class,
491                        { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
492                        inst_flags)
493
494    if mem_flags:
495        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
496        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
497        iop.constructor += s
498        memacc_iop.constructor += s
499
500    # select templates
501
502    # The InitiateAcc template is the same for StoreCond templates as the
503    # corresponding Store template..
504    StoreCondInitiateAcc = StoreInitiateAcc
505
506    fullExecTemplate = eval(exec_template_base + 'Execute')
507    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
508    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
509
510    # (header_output, decoder_output, decode_block, exec_output)
511    return (LoadStoreDeclare.subst(iop),
512            LoadStoreConstructor.subst(iop),
513            decode_template.subst(iop),
514            fullExecTemplate.subst(iop)
515            + EACompExecute.subst(iop)
516            + initiateAccTemplate.subst(iop)
517            + completeAccTemplate.subst(iop))
518}};
519
520def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
521                     mem_flags = [], inst_flags = []) {{
522    (header_output, decoder_output, decode_block, exec_output) = \
523        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
524                      decode_template = LoadNopCheckDecode,
525                      exec_template_base = 'Load')
526}};
527
528
529// Note that the flags passed in apply only to the prefetch version
530def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
531                          mem_flags = [], pf_flags = [], inst_flags = []) {{
532    # declare the load instruction object and generate the decode block
533    (header_output, decoder_output, decode_block, exec_output) = \
534        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
535                      decode_template = LoadPrefetchCheckDecode,
536                      exec_template_base = 'Load')
537
538    # Declare the prefetch instruction object.
539
540    # Make sure flag args are lists so we can mess with them.
541    mem_flags = makeList(mem_flags)
542    pf_flags = makeList(pf_flags)
543    inst_flags = makeList(inst_flags)
544
545    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
546    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
547                                  'IsDataPrefetch', 'MemReadOp']
548
549    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
550        LoadStoreBase(name, Name + 'Prefetch', ea_code,
551                      'xc->prefetch(EA, memAccessFlags);',
552                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
553
554    header_output += pf_header_output
555    decoder_output += pf_decoder_output
556    exec_output += pf_exec_output
557}};
558
559
560def format Store(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                      exec_template_base = 'Store')
565}};
566
567
568def format StoreCond(memacc_code, postacc_code,
569                     ea_code = {{ EA = Rb + disp; }},
570                     mem_flags = [], inst_flags = []) {{
571    (header_output, decoder_output, decode_block, exec_output) = \
572        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
573                      postacc_code, exec_template_base = 'StoreCond')
574}};
575
576
577// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
578def format MiscPrefetch(ea_code, memacc_code,
579                        mem_flags = [], inst_flags = []) {{
580    (header_output, decoder_output, decode_block, exec_output) = \
581        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
582                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
583}};
584
585
586