mem.isa revision 2068
16691Stjones1@inf.ed.ac.uk// -*- mode:c++ -*-
26691Stjones1@inf.ed.ac.uk
36691Stjones1@inf.ed.ac.uk// Copyright (c) 2003-2005 The Regents of The University of Michigan
46691Stjones1@inf.ed.ac.uk// All rights reserved.
56691Stjones1@inf.ed.ac.uk//
66691Stjones1@inf.ed.ac.uk// Redistribution and use in source and binary forms, with or without
76691Stjones1@inf.ed.ac.uk// modification, are permitted provided that the following conditions are
86691Stjones1@inf.ed.ac.uk// met: redistributions of source code must retain the above copyright
96691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer;
106691Stjones1@inf.ed.ac.uk// redistributions in binary form must reproduce the above copyright
116691Stjones1@inf.ed.ac.uk// notice, this list of conditions and the following disclaimer in the
126691Stjones1@inf.ed.ac.uk// documentation and/or other materials provided with the distribution;
136691Stjones1@inf.ed.ac.uk// neither the name of the copyright holders nor the names of its
146691Stjones1@inf.ed.ac.uk// contributors may be used to endorse or promote products derived from
156691Stjones1@inf.ed.ac.uk// this software without specific prior written permission.
166691Stjones1@inf.ed.ac.uk//
176691Stjones1@inf.ed.ac.uk// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186691Stjones1@inf.ed.ac.uk// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196691Stjones1@inf.ed.ac.uk// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206691Stjones1@inf.ed.ac.uk// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216691Stjones1@inf.ed.ac.uk// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226691Stjones1@inf.ed.ac.uk// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236691Stjones1@inf.ed.ac.uk// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246691Stjones1@inf.ed.ac.uk// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256691Stjones1@inf.ed.ac.uk// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266691Stjones1@inf.ed.ac.uk// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276691Stjones1@inf.ed.ac.uk// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286691Stjones1@inf.ed.ac.uk
296691Stjones1@inf.ed.ac.ukoutput header {{
306691Stjones1@inf.ed.ac.uk    /**
316691Stjones1@inf.ed.ac.uk     * Base class for general Alpha memory-format instructions.
326691Stjones1@inf.ed.ac.uk     */
336691Stjones1@inf.ed.ac.uk    class Memory : public AlphaStaticInst
346691Stjones1@inf.ed.ac.uk    {
356691Stjones1@inf.ed.ac.uk      protected:
366691Stjones1@inf.ed.ac.uk
376691Stjones1@inf.ed.ac.uk        /// Memory request flags.  See mem_req_base.hh.
386691Stjones1@inf.ed.ac.uk        unsigned memAccessFlags;
396691Stjones1@inf.ed.ac.uk        /// Pointer to EAComp object.
406691Stjones1@inf.ed.ac.uk        const StaticInstPtr<AlphaISA> eaCompPtr;
416691Stjones1@inf.ed.ac.uk        /// Pointer to MemAcc object.
426691Stjones1@inf.ed.ac.uk        const StaticInstPtr<AlphaISA> memAccPtr;
436691Stjones1@inf.ed.ac.uk
446691Stjones1@inf.ed.ac.uk        /// Constructor
456691Stjones1@inf.ed.ac.uk        Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
466691Stjones1@inf.ed.ac.uk               StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
476691Stjones1@inf.ed.ac.uk               StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
486691Stjones1@inf.ed.ac.uk            : AlphaStaticInst(mnem, _machInst, __opClass),
496691Stjones1@inf.ed.ac.uk              memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
506691Stjones1@inf.ed.ac.uk        {
516691Stjones1@inf.ed.ac.uk        }
526691Stjones1@inf.ed.ac.uk
536691Stjones1@inf.ed.ac.uk        std::string
546691Stjones1@inf.ed.ac.uk        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
556691Stjones1@inf.ed.ac.uk
566691Stjones1@inf.ed.ac.uk      public:
576691Stjones1@inf.ed.ac.uk
586691Stjones1@inf.ed.ac.uk        const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
596691Stjones1@inf.ed.ac.uk        const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
606691Stjones1@inf.ed.ac.uk    };
616691Stjones1@inf.ed.ac.uk
626691Stjones1@inf.ed.ac.uk    /**
636691Stjones1@inf.ed.ac.uk     * Base class for memory-format instructions using a 32-bit
646691Stjones1@inf.ed.ac.uk     * displacement (i.e. most of them).
656691Stjones1@inf.ed.ac.uk     */
666691Stjones1@inf.ed.ac.uk    class MemoryDisp32 : public Memory
676691Stjones1@inf.ed.ac.uk    {
686691Stjones1@inf.ed.ac.uk      protected:
696691Stjones1@inf.ed.ac.uk        /// Displacement for EA calculation (signed).
706691Stjones1@inf.ed.ac.uk        int32_t disp;
716691Stjones1@inf.ed.ac.uk
726691Stjones1@inf.ed.ac.uk        /// Constructor.
736691Stjones1@inf.ed.ac.uk        MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
746691Stjones1@inf.ed.ac.uk                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
756691Stjones1@inf.ed.ac.uk                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
766691Stjones1@inf.ed.ac.uk            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
776691Stjones1@inf.ed.ac.uk              disp(MEMDISP)
786691Stjones1@inf.ed.ac.uk        {
796972Stjones1@inf.ed.ac.uk        }
806972Stjones1@inf.ed.ac.uk    };
816972Stjones1@inf.ed.ac.uk
826972Stjones1@inf.ed.ac.uk
836972Stjones1@inf.ed.ac.uk    /**
846972Stjones1@inf.ed.ac.uk     * Base class for a few miscellaneous memory-format insts
856972Stjones1@inf.ed.ac.uk     * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
866972Stjones1@inf.ed.ac.uk     * None of these instructions has a destination register either.
876972Stjones1@inf.ed.ac.uk     */
886972Stjones1@inf.ed.ac.uk    class MemoryNoDisp : public Memory
896972Stjones1@inf.ed.ac.uk    {
906972Stjones1@inf.ed.ac.uk      protected:
916972Stjones1@inf.ed.ac.uk        /// Constructor
926972Stjones1@inf.ed.ac.uk        MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
936972Stjones1@inf.ed.ac.uk                     StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
946972Stjones1@inf.ed.ac.uk                     StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
956691Stjones1@inf.ed.ac.uk            : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
966691Stjones1@inf.ed.ac.uk        {
976691Stjones1@inf.ed.ac.uk        }
986691Stjones1@inf.ed.ac.uk
996691Stjones1@inf.ed.ac.uk        std::string
1006691Stjones1@inf.ed.ac.uk        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1016691Stjones1@inf.ed.ac.uk    };
1026691Stjones1@inf.ed.ac.uk}};
1036691Stjones1@inf.ed.ac.uk
104
105output decoder {{
106    std::string
107    Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
108    {
109        return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
110                        flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
111    }
112
113    std::string
114    MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
115    {
116        return csprintf("%-10s (r%d)", mnemonic, RB);
117    }
118}};
119
120def format LoadAddress(code) {{
121    iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
122    header_output = BasicDeclare.subst(iop)
123    decoder_output = BasicConstructor.subst(iop)
124    decode_block = BasicDecode.subst(iop)
125    exec_output = BasicExecute.subst(iop)
126}};
127
128
129def template LoadStoreDeclare {{
130    /**
131     * Static instruction class for "%(mnemonic)s".
132     */
133    class %(class_name)s : public %(base_class)s
134    {
135      protected:
136
137        /**
138         * "Fake" effective address computation class for "%(mnemonic)s".
139         */
140        class EAComp : public %(base_class)s
141        {
142          public:
143            /// Constructor
144            EAComp(MachInst machInst);
145
146            %(BasicExecDeclare)s
147        };
148
149        /**
150         * "Fake" memory access instruction class for "%(mnemonic)s".
151         */
152        class MemAcc : public %(base_class)s
153        {
154          public:
155            /// Constructor
156            MemAcc(MachInst machInst);
157
158            %(BasicExecDeclare)s
159        };
160
161      public:
162
163        /// Constructor.
164        %(class_name)s(MachInst machInst);
165
166        %(BasicExecDeclare)s
167    };
168}};
169
170def template LoadStoreConstructor {{
171    /** TODO: change op_class to AddrGenOp or something (requires
172     * creating new member of OpClass enum in op_class.hh, updating
173     * config files, etc.). */
174    inline %(class_name)s::EAComp::EAComp(MachInst machInst)
175        : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
176    {
177        %(ea_constructor)s;
178    }
179
180    inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
181        : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
182    {
183        %(memacc_constructor)s;
184    }
185
186    inline %(class_name)s::%(class_name)s(MachInst machInst)
187         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
188                          new EAComp(machInst), new MemAcc(machInst))
189    {
190        %(constructor)s;
191    }
192}};
193
194
195def template EACompExecute {{
196    Fault
197    %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
198                                   Trace::InstRecord *traceData) const
199    {
200        Addr EA;
201        Fault fault = No_Fault;
202
203        %(fp_enable_check)s;
204        %(op_decl)s;
205        %(op_rd)s;
206        %(code)s;
207
208        if (fault == No_Fault) {
209            %(op_wb)s;
210            xc->setEA(EA);
211        }
212
213        return fault;
214    }
215}};
216
217def template MemAccExecute {{
218    Fault
219    %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
220                                   Trace::InstRecord *traceData) const
221    {
222        Addr EA;
223        Fault fault = No_Fault;
224
225        %(fp_enable_check)s;
226        %(op_decl)s;
227        %(op_nonmem_rd)s;
228        EA = xc->getEA();
229
230        if (fault == No_Fault) {
231            %(op_mem_rd)s;
232            %(code)s;
233        }
234
235        if (fault == No_Fault) {
236            %(op_mem_wb)s;
237        }
238
239        if (fault == No_Fault) {
240            %(postacc_code)s;
241        }
242
243        if (fault == No_Fault) {
244            %(op_nonmem_wb)s;
245        }
246
247        return fault;
248    }
249}};
250
251
252def template LoadStoreExecute {{
253    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
254                                  Trace::InstRecord *traceData) const
255    {
256        Addr EA;
257        Fault fault = No_Fault;
258
259        %(fp_enable_check)s;
260        %(op_decl)s;
261        %(op_nonmem_rd)s;
262        %(ea_code)s;
263
264        if (fault == No_Fault) {
265            %(op_mem_rd)s;
266            %(memacc_code)s;
267        }
268
269        if (fault == No_Fault) {
270            %(op_mem_wb)s;
271        }
272
273        if (fault == No_Fault) {
274            %(postacc_code)s;
275        }
276
277        if (fault == No_Fault) {
278            %(op_nonmem_wb)s;
279        }
280
281        return fault;
282    }
283}};
284
285
286def template PrefetchExecute {{
287    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
288                                  Trace::InstRecord *traceData) const
289    {
290        Addr EA;
291        Fault fault = No_Fault;
292
293        %(fp_enable_check)s;
294        %(op_decl)s;
295        %(op_nonmem_rd)s;
296        %(ea_code)s;
297
298        if (fault == No_Fault) {
299            xc->prefetch(EA, memAccessFlags);
300        }
301
302        return No_Fault;
303    }
304}};
305
306// load instructions use Ra as dest, so check for
307// Ra == 31 to detect nops
308def template LoadNopCheckDecode {{
309 {
310     AlphaStaticInst *i = new %(class_name)s(machInst);
311     if (RA == 31) {
312         i = makeNop(i);
313     }
314     return i;
315 }
316}};
317
318
319// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
320def template LoadPrefetchCheckDecode {{
321 {
322     if (RA != 31) {
323         return new %(class_name)s(machInst);
324     }
325     else {
326         return new %(class_name)sPrefetch(machInst);
327     }
328 }
329}};
330
331
332let {{
333def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
334                  base_class = 'MemoryDisp32', flags = [],
335                  decode_template = BasicDecode,
336                  exec_template = LoadStoreExecute):
337    # Segregate flags into instruction flags (handled by InstObjParams)
338    # and memory access flags (handled here).
339
340    # Would be nice to autogenerate this list, but oh well.
341    valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
342    mem_flags =  [f for f in flags if f in valid_mem_flags]
343    inst_flags = [f for f in flags if f not in valid_mem_flags]
344
345    # add hook to get effective addresses into execution trace output.
346    ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
347
348    # generate code block objects
349    ea_cblk = CodeBlock(ea_code)
350    memacc_cblk = CodeBlock(memacc_code)
351    postacc_cblk = CodeBlock(postacc_code)
352
353    # Some CPU models execute the memory operation as an atomic unit,
354    # while others want to separate them into an effective address
355    # computation and a memory access operation.  As a result, we need
356    # to generate three StaticInst objects.  Note that the latter two
357    # are nested inside the larger "atomic" one.
358
359    # generate InstObjParams for EAComp object
360    ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
361
362    # generate InstObjParams for MemAcc object
363    memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
364    # in the split execution model, the MemAcc portion is responsible
365    # for the post-access code.
366    memacc_iop.postacc_code = postacc_cblk.code
367
368    # generate InstObjParams for unified execution
369    cblk = CodeBlock(ea_code + memacc_code + postacc_code)
370    iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
371
372    iop.ea_constructor = ea_cblk.constructor
373    iop.ea_code = ea_cblk.code
374    iop.memacc_constructor = memacc_cblk.constructor
375    iop.memacc_code = memacc_cblk.code
376    iop.postacc_code = postacc_cblk.code
377
378    if mem_flags:
379        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
380        iop.constructor += s
381        memacc_iop.constructor += s
382
383    # (header_output, decoder_output, decode_block, exec_output)
384    return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
385            decode_template.subst(iop),
386            EACompExecute.subst(ea_iop)
387            + MemAccExecute.subst(memacc_iop)
388            + exec_template.subst(iop))
389}};
390
391
392def format LoadOrNop(ea_code, memacc_code, *flags) {{
393    (header_output, decoder_output, decode_block, exec_output) = \
394        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
395                      decode_template = LoadNopCheckDecode)
396}};
397
398
399// Note that the flags passed in apply only to the prefetch version
400def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
401    # declare the load instruction object and generate the decode block
402    (header_output, decoder_output, decode_block, exec_output) = \
403        LoadStoreBase(name, Name, ea_code, memacc_code,
404                      decode_template = LoadPrefetchCheckDecode)
405
406    # Declare the prefetch instruction object.
407
408    # convert flags from tuple to list to make them mutable
409    pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
410
411    (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
412        LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
413                      flags = pf_flags, exec_template = PrefetchExecute)
414
415    header_output += pf_header_output
416    decoder_output += pf_decoder_output
417    exec_output += pf_exec_output
418}};
419
420
421def format Store(ea_code, memacc_code, *flags) {{
422    (header_output, decoder_output, decode_block, exec_output) = \
423        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags)
424}};
425
426
427def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
428    (header_output, decoder_output, decode_block, exec_output) = \
429        LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
430                      flags = flags)
431}};
432
433
434// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
435def format MiscPrefetch(ea_code, memacc_code, *flags) {{
436    (header_output, decoder_output, decode_block, exec_output) = \
437        LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
438                      base_class = 'MemoryNoDisp')
439}};
440
441
442