mem.isa revision 6181:19fedb1e5ded
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 MiscMemAccSize {{
168    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
169    {
170        panic("Misc instruction does not support split access method!");
171        return 0;
172    }
173}};
174
175def template LoadStoreMemAccSize {{
176    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
177    {
178        // Return the memory access size in bytes
179        return (%(mem_acc_size)d / 8);
180    }
181}};
182
183
184def template LoadStoreConstructor {{
185    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
186         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
187    {
188        %(constructor)s;
189    }
190}};
191
192def template EACompExecute {{
193    Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
194                                  Trace::InstRecord *traceData) const
195    {
196        Addr EA;
197        Fault fault = NoFault;
198
199        %(fp_enable_check)s;
200        %(op_decl)s;
201        %(op_rd)s;
202        %(ea_code)s;
203
204        if (fault == NoFault) {
205            %(op_wb)s;
206            xc->setEA(EA);
207        }
208
209        return fault;
210    }
211}};
212
213
214def template LoadExecute {{
215    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
216                                  Trace::InstRecord *traceData) const
217    {
218        Addr EA;
219        Fault fault = NoFault;
220
221        %(fp_enable_check)s;
222        %(op_decl)s;
223        %(op_rd)s;
224        %(ea_code)s;
225
226        if (fault == NoFault) {
227            fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
228            %(memacc_code)s;
229        }
230
231        if (fault == NoFault) {
232            %(op_wb)s;
233        }
234
235        return fault;
236    }
237}};
238
239
240def template LoadInitiateAcc {{
241    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
242                                      Trace::InstRecord *traceData) const
243    {
244        Addr EA;
245        Fault fault = NoFault;
246
247        %(fp_enable_check)s;
248        %(op_src_decl)s;
249        %(op_rd)s;
250        %(ea_code)s;
251
252        if (fault == NoFault) {
253            fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
254        }
255
256        return fault;
257    }
258}};
259
260
261def template LoadCompleteAcc {{
262    Fault %(class_name)s::completeAcc(PacketPtr pkt,
263                                      %(CPU_exec_context)s *xc,
264                                      Trace::InstRecord *traceData) const
265    {
266        Fault fault = NoFault;
267
268        %(fp_enable_check)s;
269        %(op_decl)s;
270
271        Mem = pkt->get<typeof(Mem)>();
272
273        if (fault == NoFault) {
274            %(memacc_code)s;
275        }
276
277        if (fault == NoFault) {
278            %(op_wb)s;
279        }
280
281        return fault;
282    }
283}};
284
285
286def template StoreExecute {{
287    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
288                                  Trace::InstRecord *traceData) const
289    {
290        Addr EA;
291        Fault fault = NoFault;
292
293        %(fp_enable_check)s;
294        %(op_decl)s;
295        %(op_rd)s;
296        %(ea_code)s;
297
298        if (fault == NoFault) {
299            %(memacc_code)s;
300        }
301
302        if (fault == NoFault) {
303            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
304                              memAccessFlags, NULL);
305            if (traceData) { traceData->setData(Mem); }
306        }
307
308        if (fault == NoFault) {
309            %(postacc_code)s;
310        }
311
312        if (fault == NoFault) {
313            %(op_wb)s;
314        }
315
316        return fault;
317    }
318}};
319
320def template StoreCondExecute {{
321    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
322                                  Trace::InstRecord *traceData) const
323    {
324        Addr EA;
325        Fault fault = NoFault;
326        uint64_t write_result = 0;
327
328        %(fp_enable_check)s;
329        %(op_decl)s;
330        %(op_rd)s;
331        %(ea_code)s;
332
333        if (fault == NoFault) {
334            %(memacc_code)s;
335        }
336
337        if (fault == NoFault) {
338            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
339                              memAccessFlags, &write_result);
340            if (traceData) { traceData->setData(Mem); }
341        }
342
343        if (fault == NoFault) {
344            %(postacc_code)s;
345        }
346
347        if (fault == NoFault) {
348            %(op_wb)s;
349        }
350
351        return fault;
352    }
353}};
354
355def template StoreInitiateAcc {{
356    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
357                                      Trace::InstRecord *traceData) const
358    {
359        Addr EA;
360        Fault fault = NoFault;
361
362        %(fp_enable_check)s;
363        %(op_decl)s;
364        %(op_rd)s;
365        %(ea_code)s;
366
367        if (fault == NoFault) {
368            %(memacc_code)s;
369        }
370
371        if (fault == NoFault) {
372            fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
373                              memAccessFlags, NULL);
374            if (traceData) { traceData->setData(Mem); }
375        }
376
377        return fault;
378    }
379}};
380
381
382def template StoreCompleteAcc {{
383    Fault %(class_name)s::completeAcc(PacketPtr pkt,
384                                      %(CPU_exec_context)s *xc,
385                                      Trace::InstRecord *traceData) const
386    {
387        Fault fault = NoFault;
388
389        %(fp_enable_check)s;
390        %(op_dest_decl)s;
391
392        if (fault == NoFault) {
393            %(postacc_code)s;
394        }
395
396        if (fault == NoFault) {
397            %(op_wb)s;
398        }
399
400        return fault;
401    }
402}};
403
404
405def template StoreCondCompleteAcc {{
406    Fault %(class_name)s::completeAcc(PacketPtr pkt,
407                                      %(CPU_exec_context)s *xc,
408                                      Trace::InstRecord *traceData) const
409    {
410        Fault fault = NoFault;
411
412        %(fp_enable_check)s;
413        %(op_dest_decl)s;
414
415        uint64_t write_result = pkt->req->getExtraData();
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
430def template MiscExecute {{
431    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
432                                  Trace::InstRecord *traceData) const
433    {
434        Addr EA;
435        Fault fault = NoFault;
436
437        %(fp_enable_check)s;
438        %(op_decl)s;
439        %(op_rd)s;
440        %(ea_code)s;
441
442        if (fault == NoFault) {
443            %(memacc_code)s;
444        }
445
446        return NoFault;
447    }
448}};
449
450def template MiscInitiateAcc {{
451    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
452                                      Trace::InstRecord *traceData) const
453    {
454        warn("Misc instruction does not support split access method!");
455        return NoFault;
456    }
457}};
458
459
460def template MiscCompleteAcc {{
461    Fault %(class_name)s::completeAcc(PacketPtr pkt,
462                                      %(CPU_exec_context)s *xc,
463                                      Trace::InstRecord *traceData) const
464    {
465        warn("Misc instruction does not support split access method!");
466
467        return NoFault;
468    }
469}};
470
471def template MiscMemAccSize {{
472    int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc)
473    {
474        panic("Misc instruction does not support split access method!");
475        return 0;
476    }
477}};
478
479// load instructions use Ra as dest, so check for
480// Ra == 31 to detect nops
481def template LoadNopCheckDecode {{
482 {
483     AlphaStaticInst *i = new %(class_name)s(machInst);
484     if (RA == 31) {
485         i = makeNop(i);
486     }
487     return i;
488 }
489}};
490
491
492// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
493def template LoadPrefetchCheckDecode {{
494 {
495     if (RA != 31) {
496         return new %(class_name)s(machInst);
497     }
498     else {
499         return new %(class_name)sPrefetch(machInst);
500     }
501 }
502}};
503
504
505let {{
506def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
507                  postacc_code = '', base_class = 'MemoryDisp32',
508                  decode_template = BasicDecode, exec_template_base = ''):
509    # Make sure flags are in lists (convert to lists if not).
510    mem_flags = makeList(mem_flags)
511    inst_flags = makeList(inst_flags)
512
513    # add hook to get effective addresses into execution trace output.
514    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
515
516    # Some CPU models execute the memory operation as an atomic unit,
517    # while others want to separate them into an effective address
518    # computation and a memory access operation.  As a result, we need
519    # to generate three StaticInst objects.  Note that the latter two
520    # are nested inside the larger "atomic" one.
521
522    # Generate InstObjParams for each of the three objects.  Note that
523    # they differ only in the set of code objects contained (which in
524    # turn affects the object's overall operand list).
525    iop = InstObjParams(name, Name, base_class,
526                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
527                        inst_flags)
528    memacc_iop = InstObjParams(name, Name, base_class,
529                        { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
530                        inst_flags)
531
532    if mem_flags:
533        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
534        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
535        iop.constructor += s
536        memacc_iop.constructor += s
537
538    # select templates
539
540    # The InitiateAcc template is the same for StoreCond templates as the
541    # corresponding Store template..
542    StoreCondInitiateAcc = StoreInitiateAcc
543
544    fullExecTemplate = eval(exec_template_base + 'Execute')
545    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
546    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
547
548    if (exec_template_base == 'Load' or exec_template_base == 'Store'):
549      memAccSizeTemplate = eval('LoadStoreMemAccSize')
550    else:
551      memAccSizeTemplate = eval('MiscMemAccSize')
552
553    # (header_output, decoder_output, decode_block, exec_output)
554    return (LoadStoreDeclare.subst(iop),
555            LoadStoreConstructor.subst(iop),
556            decode_template.subst(iop),
557            fullExecTemplate.subst(iop)
558            + EACompExecute.subst(iop)
559            + initiateAccTemplate.subst(iop)
560            + completeAccTemplate.subst(iop)
561            + memAccSizeTemplate.subst(memacc_iop))
562}};
563
564def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
565                     mem_flags = [], inst_flags = []) {{
566    (header_output, decoder_output, decode_block, exec_output) = \
567        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
568                      decode_template = LoadNopCheckDecode,
569                      exec_template_base = 'Load')
570}};
571
572
573// Note that the flags passed in apply only to the prefetch version
574def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
575                          mem_flags = [], pf_flags = [], inst_flags = []) {{
576    # declare the load instruction object and generate the decode block
577    (header_output, decoder_output, decode_block, exec_output) = \
578        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
579                      decode_template = LoadPrefetchCheckDecode,
580                      exec_template_base = 'Load')
581
582    # Declare the prefetch instruction object.
583
584    # Make sure flag args are lists so we can mess with them.
585    mem_flags = makeList(mem_flags)
586    pf_flags = makeList(pf_flags)
587    inst_flags = makeList(inst_flags)
588
589    pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
590    pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
591                                  'IsDataPrefetch', 'MemReadOp']
592
593    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
594        LoadStoreBase(name, Name + 'Prefetch', ea_code,
595                      'xc->prefetch(EA, memAccessFlags);',
596                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
597
598    header_output += pf_header_output
599    decoder_output += pf_decoder_output
600    exec_output += pf_exec_output
601}};
602
603
604def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
605                 mem_flags = [], inst_flags = []) {{
606    (header_output, decoder_output, decode_block, exec_output) = \
607        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
608                      exec_template_base = 'Store')
609}};
610
611
612def format StoreCond(memacc_code, postacc_code,
613                     ea_code = {{ EA = Rb + disp; }},
614                     mem_flags = [], inst_flags = []) {{
615    (header_output, decoder_output, decode_block, exec_output) = \
616        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
617                      postacc_code, exec_template_base = 'StoreCond')
618}};
619
620
621// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
622def format MiscPrefetch(ea_code, memacc_code,
623                        mem_flags = [], inst_flags = []) {{
624    (header_output, decoder_output, decode_block, exec_output) = \
625        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
626                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
627}};
628
629
630