mem.isa revision 12236:126ac9da6050
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        Fault execute(ExecContext *, Trace::InstRecord *) const;
133        Fault eaComp(ExecContext *, Trace::InstRecord *) const;
134        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const;
135        Fault completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
136    };
137}};
138
139def template LoadStoreConstructor {{
140    %(class_name)s::%(class_name)s(ExtMachInst machInst)
141         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
142    {
143        %(constructor)s;
144    }
145}};
146
147def template EACompExecute {{
148    Fault %(class_name)s::eaComp(ExecContext *xc,
149                                 Trace::InstRecord *traceData) const
150    {
151        Addr EA;
152        Fault fault = NoFault;
153
154        %(fp_enable_check)s;
155        %(op_decl)s;
156        %(op_rd)s;
157        %(ea_code)s;
158
159        if (fault == NoFault) {
160            %(op_wb)s;
161            xc->setEA(EA);
162        }
163
164        return fault;
165    }
166}};
167
168
169def template LoadExecute {{
170    Fault %(class_name)s::execute(ExecContext *xc,
171                                  Trace::InstRecord *traceData) const
172    {
173        Addr EA;
174        Fault fault = NoFault;
175
176        %(fp_enable_check)s;
177        %(op_decl)s;
178        %(op_rd)s;
179        %(ea_code)s;
180
181        if (fault == NoFault) {
182            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
183            %(memacc_code)s;
184        }
185
186        if (fault == NoFault) {
187            %(op_wb)s;
188        }
189
190        return fault;
191    }
192}};
193
194
195def template LoadInitiateAcc {{
196    Fault %(class_name)s::initiateAcc(ExecContext *xc,
197                                      Trace::InstRecord *traceData) const
198    {
199        Addr EA;
200        Fault fault = NoFault;
201
202        %(fp_enable_check)s;
203        %(op_src_decl)s;
204        %(op_rd)s;
205        %(ea_code)s;
206
207        if (fault == NoFault) {
208            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
209        }
210
211        return fault;
212    }
213}};
214
215
216def template LoadCompleteAcc {{
217    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
218                                      Trace::InstRecord *traceData) const
219    {
220        Fault fault = NoFault;
221
222        %(fp_enable_check)s;
223        %(op_decl)s;
224
225        getMem(pkt, Mem, traceData);
226
227        if (fault == NoFault) {
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 StoreExecute {{
241    Fault %(class_name)s::execute(ExecContext *xc,
242                                  Trace::InstRecord *traceData) const
243    {
244        Addr EA;
245        Fault fault = NoFault;
246
247        %(fp_enable_check)s;
248        %(op_decl)s;
249        %(op_rd)s;
250        %(ea_code)s;
251
252        if (fault == NoFault) {
253            %(memacc_code)s;
254        }
255
256        if (fault == NoFault) {
257            fault = writeMemAtomic(xc, traceData, Mem, EA,
258                    memAccessFlags, NULL);
259        }
260
261        if (fault == NoFault) {
262            %(postacc_code)s;
263        }
264
265        if (fault == NoFault) {
266            %(op_wb)s;
267        }
268
269        return fault;
270    }
271}};
272
273def template StoreCondExecute {{
274    Fault %(class_name)s::execute(ExecContext *xc,
275                                  Trace::InstRecord *traceData) const
276    {
277        Addr EA;
278        Fault fault = NoFault;
279        uint64_t write_result = 0;
280
281        %(fp_enable_check)s;
282        %(op_decl)s;
283        %(op_rd)s;
284        %(ea_code)s;
285
286        if (fault == NoFault) {
287            %(memacc_code)s;
288        }
289
290        if (fault == NoFault) {
291            fault = writeMemAtomic(xc, traceData, Mem, EA,
292                    memAccessFlags, &write_result);
293        }
294
295        if (fault == NoFault) {
296            %(postacc_code)s;
297        }
298
299        if (fault == NoFault) {
300            %(op_wb)s;
301        }
302
303        return fault;
304    }
305}};
306
307def template StoreInitiateAcc {{
308    Fault %(class_name)s::initiateAcc(ExecContext *xc,
309                                      Trace::InstRecord *traceData) const
310    {
311        Addr EA;
312        Fault fault = NoFault;
313
314        %(fp_enable_check)s;
315        %(op_decl)s;
316        %(op_rd)s;
317        %(ea_code)s;
318
319        if (fault == NoFault) {
320            %(memacc_code)s;
321        }
322
323        if (fault == NoFault) {
324            fault = writeMemTiming(xc, traceData, Mem, EA,
325                    memAccessFlags, NULL);
326        }
327
328        return fault;
329    }
330}};
331
332
333def template StoreCompleteAcc {{
334    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
335                                      Trace::InstRecord *traceData) const
336    {
337        return NoFault;
338    }
339}};
340
341
342def template StoreCondCompleteAcc {{
343    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
344                                      Trace::InstRecord *traceData) const
345    {
346        Fault fault = NoFault;
347
348        %(fp_enable_check)s;
349        %(op_dest_decl)s;
350
351        uint64_t write_result = pkt->req->getExtraData();
352
353        if (fault == NoFault) {
354            %(postacc_code)s;
355        }
356
357        if (fault == NoFault) {
358            %(op_wb)s;
359        }
360
361        return fault;
362    }
363}};
364
365
366def template MiscExecute {{
367    Fault %(class_name)s::execute(ExecContext *xc,
368                                  Trace::InstRecord *traceData) const
369    {
370        Addr EA M5_VAR_USED;
371        Fault fault = NoFault;
372
373        %(fp_enable_check)s;
374        %(op_decl)s;
375        %(op_rd)s;
376        %(ea_code)s;
377
378        warn_once("Prefetch instructions in Alpha do not do anything\n");
379        if (fault == NoFault) {
380            %(memacc_code)s;
381        }
382
383        return NoFault;
384    }
385}};
386
387// Prefetches in Alpha don't actually do anything
388// They just build an effective address and complete
389def template MiscInitiateAcc {{
390    Fault %(class_name)s::initiateAcc(ExecContext *xc,
391                                      Trace::InstRecord *traceData) const
392    {
393        warn("initiateAcc undefined: Misc instruction does not support split "
394             "access method!");
395        return NoFault;
396    }
397}};
398
399
400def template MiscCompleteAcc {{
401    Fault %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
402                                      Trace::InstRecord *traceData) const
403    {
404        warn("completeAcc undefined: Misc instruction does not support split "
405             "access method!");
406
407        return NoFault;
408    }
409}};
410
411
412// load instructions use Ra as dest, so check for
413// Ra == 31 to detect nops
414def template LoadNopCheckDecode {{
415 {
416     AlphaStaticInst *i = new %(class_name)s(machInst);
417     if (RA == 31) {
418         i = makeNop(i);
419     }
420     return i;
421 }
422}};
423
424
425// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
426def template LoadPrefetchCheckDecode {{
427 {
428     if (RA != 31) {
429         return new %(class_name)s(machInst);
430     }
431     else {
432         return new %(class_name)sPrefetch(machInst);
433     }
434 }
435}};
436
437
438let {{
439def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
440                  postacc_code = '', base_class = 'MemoryDisp32',
441                  decode_template = BasicDecode, exec_template_base = ''):
442    # Make sure flags are in lists (convert to lists if not).
443    mem_flags = makeList(mem_flags)
444    inst_flags = makeList(inst_flags)
445
446    iop = InstObjParams(name, Name, base_class,
447                        { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
448                        inst_flags)
449
450    if mem_flags:
451        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
452        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
453        iop.constructor += s
454
455    # select templates
456
457    # The InitiateAcc template is the same for StoreCond templates as the
458    # corresponding Store template..
459    StoreCondInitiateAcc = StoreInitiateAcc
460
461    fullExecTemplate = eval(exec_template_base + 'Execute')
462    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
463    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
464
465    # (header_output, decoder_output, decode_block, exec_output)
466    return (LoadStoreDeclare.subst(iop),
467            LoadStoreConstructor.subst(iop),
468            decode_template.subst(iop),
469            fullExecTemplate.subst(iop)
470            + EACompExecute.subst(iop)
471            + initiateAccTemplate.subst(iop)
472            + completeAccTemplate.subst(iop))
473}};
474
475def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
476                     mem_flags = [], inst_flags = []) {{
477    (header_output, decoder_output, decode_block, exec_output) = \
478        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
479                      decode_template = LoadNopCheckDecode,
480                      exec_template_base = 'Load')
481}};
482
483
484// Note that the flags passed in apply only to the prefetch version
485def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
486                          mem_flags = [], pf_flags = [], inst_flags = []) {{
487    # declare the load instruction object and generate the decode block
488    (header_output, decoder_output, decode_block, exec_output) = \
489        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
490                      decode_template = LoadPrefetchCheckDecode,
491                      exec_template_base = 'Load')
492
493    # Declare the prefetch instruction object.
494
495    # Make sure flag args are lists so we can mess with them.
496    mem_flags = makeList(mem_flags)
497    pf_flags = makeList(pf_flags)
498    inst_flags = makeList(inst_flags)
499
500    pf_mem_flags = mem_flags + pf_flags + ['PREFETCH']
501    pf_inst_flags = inst_flags
502
503    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
504        LoadStoreBase(name, Name + 'Prefetch', ea_code, ';',
505                      pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
506
507    header_output += pf_header_output
508    decoder_output += pf_decoder_output
509    exec_output += pf_exec_output
510}};
511
512
513def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
514                 mem_flags = [], inst_flags = []) {{
515    (header_output, decoder_output, decode_block, exec_output) = \
516        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
517                      exec_template_base = 'Store')
518}};
519
520
521def format StoreCond(memacc_code, postacc_code,
522                     ea_code = {{ EA = Rb + disp; }},
523                     mem_flags = [], inst_flags = []) {{
524    (header_output, decoder_output, decode_block, exec_output) = \
525        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
526                      postacc_code, exec_template_base = 'StoreCond')
527}};
528
529
530// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
531def format MiscPrefetch(ea_code, memacc_code,
532                        mem_flags = [], inst_flags = []) {{
533    (header_output, decoder_output, decode_block, exec_output) = \
534        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
535                      base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
536}};
537
538
539