mem.isa revision 11303
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    %(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 *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 *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 = readMemAtomic(xc, traceData, EA, 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 *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 = initiateMemRead(xc, traceData, EA, 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 *xc,
237                                      Trace::InstRecord *traceData) const
238    {
239        Fault fault = NoFault;
240
241        %(fp_enable_check)s;
242        %(op_decl)s;
243
244        getMem(pkt, Mem, traceData);
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 *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 = writeMemAtomic(xc, traceData, 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 *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 = writeMemAtomic(xc, traceData, 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 *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 = writeMemTiming(xc, traceData, 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 *xc,
355                                      Trace::InstRecord *traceData) const
356    {
357        return NoFault;
358    }
359}};
360
361
362def template StoreCondCompleteAcc {{
363    Fault %(class_name)s::completeAcc(PacketPtr pkt,
364                                      CPU_EXEC_CONTEXT *xc,
365                                      Trace::InstRecord *traceData) const
366    {
367        Fault fault = NoFault;
368
369        %(fp_enable_check)s;
370        %(op_dest_decl)s;
371
372        uint64_t write_result = pkt->req->getExtraData();
373
374        if (fault == NoFault) {
375            %(postacc_code)s;
376        }
377
378        if (fault == NoFault) {
379            %(op_wb)s;
380        }
381
382        return fault;
383    }
384}};
385
386
387def template MiscExecute {{
388    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
389                                  Trace::InstRecord *traceData) const
390    {
391        Addr EA M5_VAR_USED;
392        Fault fault = NoFault;
393
394        %(fp_enable_check)s;
395        %(op_decl)s;
396        %(op_rd)s;
397        %(ea_code)s;
398
399        warn_once("Prefetch instructions in Alpha do not do anything\n");
400        if (fault == NoFault) {
401            %(memacc_code)s;
402        }
403
404        return NoFault;
405    }
406}};
407
408// Prefetches in Alpha don't actually do anything
409// They just build an effective address and complete
410def template MiscInitiateAcc {{
411    Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
412                                      Trace::InstRecord *traceData) const
413    {
414        warn("initiateAcc undefined: Misc instruction does not support split "
415             "access method!");
416        return NoFault;
417    }
418}};
419
420
421def template MiscCompleteAcc {{
422    Fault %(class_name)s::completeAcc(PacketPtr pkt,
423                                      CPU_EXEC_CONTEXT *xc,
424                                      Trace::InstRecord *traceData) const
425    {
426        warn("completeAcc undefined: Misc instruction does not support split "
427             "access method!");
428
429        return NoFault;
430    }
431}};
432
433
434// load instructions use Ra as dest, so check for
435// Ra == 31 to detect nops
436def template LoadNopCheckDecode {{
437 {
438     AlphaStaticInst *i = new %(class_name)s(machInst);
439     if (RA == 31) {
440         i = makeNop(i);
441     }
442     return i;
443 }
444}};
445
446
447// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
448def template LoadPrefetchCheckDecode {{
449 {
450     if (RA != 31) {
451         return new %(class_name)s(machInst);
452     }
453     else {
454         return new %(class_name)sPrefetch(machInst);
455     }
456 }
457}};
458
459
460let {{
461def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
462                  postacc_code = '', base_class = 'MemoryDisp32',
463                  decode_template = BasicDecode, exec_template_base = ''):
464    # Make sure flags are in lists (convert to lists if not).
465    mem_flags = makeList(mem_flags)
466    inst_flags = makeList(inst_flags)
467
468    iop = InstObjParams(name, Name, base_class,
469                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
470                        inst_flags)
471
472    if mem_flags:
473        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
474        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
475        iop.constructor += s
476
477    # select templates
478
479    # The InitiateAcc template is the same for StoreCond templates as the
480    # corresponding Store template..
481    StoreCondInitiateAcc = StoreInitiateAcc
482
483    fullExecTemplate = eval(exec_template_base + 'Execute')
484    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
485    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
486
487    # (header_output, decoder_output, decode_block, exec_output)
488    return (LoadStoreDeclare.subst(iop),
489            LoadStoreConstructor.subst(iop),
490            decode_template.subst(iop),
491            fullExecTemplate.subst(iop)
492            + EACompExecute.subst(iop)
493            + initiateAccTemplate.subst(iop)
494            + completeAccTemplate.subst(iop))
495}};
496
497def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
498                     mem_flags = [], inst_flags = []) {{
499    (header_output, decoder_output, decode_block, exec_output) = \
500        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
501                      decode_template = LoadNopCheckDecode,
502                      exec_template_base = 'Load')
503}};
504
505
506// Note that the flags passed in apply only to the prefetch version
507def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
508                          mem_flags = [], pf_flags = [], inst_flags = []) {{
509    # declare the load instruction object and generate the decode block
510    (header_output, decoder_output, decode_block, exec_output) = \
511        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
512                      decode_template = LoadPrefetchCheckDecode,
513                      exec_template_base = 'Load')
514
515    # Declare the prefetch instruction object.
516
517    # Make sure flag args are lists so we can mess with them.
518    mem_flags = makeList(mem_flags)
519    pf_flags = makeList(pf_flags)
520    inst_flags = makeList(inst_flags)
521
522    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
523    pf_inst_flags = inst_flags
524
525    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
526        LoadStoreBase(name, Name + 'Prefetch', ea_code, ';',
527                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
528
529    header_output += pf_header_output
530    decoder_output += pf_decoder_output
531    exec_output += pf_exec_output
532}};
533
534
535def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
536                 mem_flags = [], inst_flags = []) {{
537    (header_output, decoder_output, decode_block, exec_output) = \
538        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
539                      exec_template_base = 'Store')
540}};
541
542
543def format StoreCond(memacc_code, postacc_code,
544                     ea_code = {{ EA = Rb + disp; }},
545                     mem_flags = [], inst_flags = []) {{
546    (header_output, decoder_output, decode_block, exec_output) = \
547        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
548                      postacc_code, exec_template_base = 'StoreCond')
549}};
550
551
552// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
553def format MiscPrefetch(ea_code, memacc_code,
554                        mem_flags = [], inst_flags = []) {{
555    (header_output, decoder_output, decode_block, exec_output) = \
556        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
557                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
558}};
559
560
561