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