mem.isa revision 11729:f37b5fcd66fe
1// -*- mode:c++ -*-
2
3// Copyright (c) 2015 RISC-V Foundation
4// Copyright (c) 2016 The University of Virginia
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met: redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer;
11// redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution;
14// neither the name of the copyright holders nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Authors: Alec Roelke
31
32////////////////////////////////////////////////////////////////////
33//
34// Memory operation instructions
35//
36output header {{
37    class Load : public RiscvStaticInst
38    {
39      public:
40        /// Displacement for EA calculation (signed).
41        int64_t ldisp;
42
43      protected:
44        /// Memory request flags.  See mem_req_base.hh.
45        Request::Flags memAccessFlags;
46
47        /// Constructor
48        Load(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
49            : RiscvStaticInst(mnem, _machInst, __opClass), ldisp(IMM12)
50        {
51            if (IMMSIGN > 0)
52                ldisp |= ~((uint64_t)0xFFF);
53        }
54
55        std::string
56        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
57    };
58
59    class Store : public RiscvStaticInst
60    {
61      public:
62        /// Displacement for EA calculation (signed).
63        int64_t sdisp;
64
65      protected:
66        /// Memory request flags.  See mem_req_base.hh.
67        Request::Flags memAccessFlags;
68
69        /// Constructor
70        Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
71            : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(IMM5)
72        {
73            sdisp |= IMM7 << 5;
74            if (IMMSIGN > 0)
75                sdisp |= ~((uint64_t)0xFFF);
76        }
77
78        std::string
79        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
80    };
81
82}};
83
84
85output decoder {{
86    std::string
87    Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const
88    {
89        std::stringstream ss;
90        ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << ldisp <<
91            '(' << regName(_srcRegIdx[0]) << ')';
92        return ss.str();
93    }
94
95    std::string
96    Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const
97    {
98        std::stringstream ss;
99        ss << mnemonic << ' ' << regName(_srcRegIdx[1]) << ", " << sdisp <<
100            '(' << regName(_srcRegIdx[0]) << ')';
101        return ss.str();
102    }
103}};
104
105def template LoadStoreDeclare {{
106    /**
107     * Static instruction class for "%(mnemonic)s".
108     */
109    class %(class_name)s : public %(base_class)s
110    {
111      public:
112        /// Constructor.
113        %(class_name)s(ExtMachInst machInst);
114
115        %(BasicExecDeclare)s
116
117        %(EACompDeclare)s
118
119        %(InitiateAccDeclare)s
120
121        %(CompleteAccDeclare)s
122    };
123}};
124
125def template EACompDeclare {{
126    Fault
127    eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
128}};
129
130def template InitiateAccDeclare {{
131    Fault
132    initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
133}};
134
135
136def template CompleteAccDeclare {{
137    Fault
138    completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
139}};
140
141def template LoadStoreConstructor {{
142    %(class_name)s::%(class_name)s(ExtMachInst machInst):
143        %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
144    {
145        %(constructor)s;
146    }
147}};
148
149def template EACompExecute {{
150    Fault
151    %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
152        Trace::InstRecord *traceData) const
153    {
154        Addr EA;
155        Fault fault = NoFault;
156
157        %(op_decl)s;
158        %(op_rd)s;
159        %(ea_code)s;
160
161        if (fault == NoFault) {
162            %(op_wb)s;
163            xc->setEA(EA);
164        }
165
166        return fault;
167    }
168}};
169
170let {{
171def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
172        base_class, postacc_code='', decode_template=BasicDecode,
173        exec_template_base=''):
174    # Make sure flags are in lists (convert to lists if not).
175    mem_flags = makeList(mem_flags)
176    inst_flags = makeList(inst_flags) # + ['IsNonSpeculative']
177
178    iop = InstObjParams(name, Name, base_class,
179        { 'ea_code':ea_code, 'memacc_code':memacc_code,
180        'postacc_code':postacc_code }, inst_flags)
181
182    if mem_flags:
183        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
184        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
185        iop.constructor += s
186
187    # select templates
188
189    # The InitiateAcc template is the same for StoreCond templates as the
190    # corresponding Store template..
191    StoreCondInitiateAcc = StoreInitiateAcc
192
193    fullExecTemplate = eval(exec_template_base + 'Execute')
194    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
195    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
196
197    # (header_output, decoder_output, decode_block, exec_output)
198    return (LoadStoreDeclare.subst(iop),
199        LoadStoreConstructor.subst(iop),
200        decode_template.subst(iop),
201        fullExecTemplate.subst(iop) +
202        EACompExecute.subst(iop) +
203        initiateAccTemplate.subst(iop) +
204        completeAccTemplate.subst(iop))
205}};
206
207def template LoadExecute {{
208    Fault
209    %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
210        Trace::InstRecord *traceData) const
211    {
212        Addr EA;
213        Fault fault = NoFault;
214
215        %(op_decl)s;
216        %(op_rd)s;
217        %(ea_code)s;
218
219        if (fault == NoFault) {
220            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
221            %(memacc_code)s;
222        }
223
224        if (fault == NoFault) {
225            %(op_wb)s;
226        }
227
228        return fault;
229    }
230}};
231
232def template LoadInitiateAcc {{
233    Fault
234    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
235        Trace::InstRecord *traceData) const
236    {
237        Addr EA;
238        Fault fault = NoFault;
239
240        %(op_src_decl)s;
241        %(op_rd)s;
242        %(ea_code)s;
243
244        if (fault == NoFault) {
245            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
246        }
247
248        return fault;
249    }
250}};
251
252def template LoadCompleteAcc {{
253    Fault
254    %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
255        Trace::InstRecord *traceData) const
256    {
257        Fault fault = NoFault;
258
259        %(op_decl)s;
260        %(op_rd)s;
261
262        getMem(pkt, Mem, traceData);
263
264        if (fault == NoFault) {
265            %(memacc_code)s;
266        }
267
268        if (fault == NoFault) {
269            %(op_wb)s;
270        }
271
272        return fault;
273    }
274}};
275
276def template StoreExecute {{
277    Fault
278    %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
279        Trace::InstRecord *traceData) const
280    {
281        Addr EA;
282        Fault fault = NoFault;
283
284        %(op_decl)s;
285        %(op_rd)s;
286        %(ea_code)s;
287
288        if (fault == NoFault) {
289            %(memacc_code)s;
290        }
291
292        if (fault == NoFault) {
293            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
294                nullptr);
295        }
296
297        if (fault == NoFault) {
298            %(postacc_code)s;
299        }
300
301        if (fault == NoFault) {
302            %(op_wb)s;
303        }
304
305        return fault;
306    }
307}};
308
309def template StoreInitiateAcc {{
310    Fault
311    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
312        Trace::InstRecord *traceData) const
313    {
314        Addr EA;
315        Fault fault = NoFault;
316
317        %(op_decl)s;
318        %(op_rd)s;
319        %(ea_code)s;
320
321        if (fault == NoFault) {
322            %(memacc_code)s;
323        }
324
325        if (fault == NoFault) {
326            fault = writeMemTiming(xc, traceData, Mem, EA,
327                memAccessFlags, nullptr);
328        }
329
330        if (fault == NoFault) {
331            %(op_wb)s;
332        }
333
334        return fault;
335    }
336}};
337
338def template StoreCompleteAcc {{
339    Fault
340    %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
341        Trace::InstRecord *traceData) const
342    {
343        return NoFault;
344    }
345}};
346
347def template StoreCondExecute {{
348    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
349        Trace::InstRecord *traceData) const
350    {
351        Addr EA;
352        Fault fault = NoFault;
353        uint64_t result;
354
355        %(op_decl)s;
356        %(op_rd)s;
357        %(ea_code)s;
358
359        if (fault == NoFault) {
360            %(memacc_code)s;
361        }
362
363        if (fault == NoFault) {
364            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
365                &result);
366            // RISC-V has the opposite convention gem5 has for success flags,
367            // so we invert the result here.
368            result = !result;
369        }
370
371        if (fault == NoFault) {
372            %(postacc_code)s;
373        }
374
375        if (fault == NoFault) {
376            %(op_wb)s;
377        }
378
379        return fault;
380    }
381}};
382
383def template StoreCondCompleteAcc {{
384    Fault %(class_name)s::completeAcc(Packet *pkt, CPU_EXEC_CONTEXT *xc,
385        Trace::InstRecord *traceData) const
386    {
387        Fault fault = NoFault;
388
389        %(op_dest_decl)s;
390
391        // RISC-V has the opposite convention gem5 has for success flags,
392        // so we invert the result here.
393        uint64_t result = !pkt->req->getExtraData();
394
395        if (fault == NoFault) {
396            %(postacc_code)s;
397        }
398
399        if (fault == NoFault) {
400            %(op_wb)s;
401        }
402
403        return fault;
404    }
405}};
406
407def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[],
408        inst_flags=[]) {{
409    (header_output, decoder_output, decode_block, exec_output) = \
410        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
411        'Load', exec_template_base='Load')
412}};
413
414def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[],
415        inst_flags=[]) {{
416    (header_output, decoder_output, decode_block, exec_output) = \
417        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
418        'Store', exec_template_base='Store')
419}};
420
421def format StoreCond(memacc_code, postacc_code, ea_code={{EA = Rs1;}},
422        mem_flags=[], inst_flags=[], aq=0, rl=0) {{
423    if aq:
424        mem_flags = makeList(mem_flags) + ["ACQUIRE"]
425    if rl:
426        mem_flags = makeList(mem_flags) + ["RELEASE"]
427    (header_output, decoder_output, decode_block, exec_output) = LoadStoreBase(
428            name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'Store',
429            postacc_code, exec_template_base='StoreCond')
430}};
431
432def format LoadReserved(memacc_code, ea_code={{EA = Rs1;}}, mem_flags=[],
433        inst_flags=[], aq=0, rl=0) {{
434    if aq:
435        mem_flags = makeList(mem_flags) + ["ACQUIRE"]
436    if rl:
437        mem_flags = makeList(mem_flags) + ["RELEASE"]
438    (header_output, decoder_output, decode_block, exec_output) = LoadStoreBase(
439            name, Name, ea_code, memacc_code, mem_flags, inst_flags, 'Load',
440            exec_template_base='Load')
441}};
442