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