mem.isa revision 12234:78ece221f9f5
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(0)
50        {}
51
52        std::string
53        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
54    };
55
56    class Store : public RiscvStaticInst
57    {
58      public:
59        /// Displacement for EA calculation (signed).
60        int64_t sdisp;
61
62      protected:
63        /// Memory request flags.  See mem_req_base.hh.
64        Request::Flags memAccessFlags;
65
66        /// Constructor
67        Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
68            : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(0)
69        {
70            sdisp = IMM5 | (IMM7 << 5);
71            if (IMMSIGN > 0)
72                sdisp |= ~((uint64_t)0xFFF);
73        }
74
75        std::string
76        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
77    };
78
79}};
80
81
82output decoder {{
83    std::string
84    Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const
85    {
86        std::stringstream ss;
87        ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", " <<
88            ldisp << '(' << registerName(_srcRegIdx[0]) << ')';
89        return ss.str();
90    }
91
92    std::string
93    Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const
94    {
95        std::stringstream ss;
96        ss << mnemonic << ' ' << registerName(_srcRegIdx[1]) << ", " <<
97            sdisp << '(' << registerName(_srcRegIdx[0]) << ')';
98        return ss.str();
99    }
100}};
101
102def template LoadStoreDeclare {{
103    /**
104     * Static instruction class for "%(mnemonic)s".
105     */
106    class %(class_name)s : public %(base_class)s
107    {
108      public:
109        /// Constructor.
110        %(class_name)s(ExtMachInst machInst);
111
112        %(BasicExecDeclare)s
113
114        %(EACompDeclare)s
115
116        %(InitiateAccDeclare)s
117
118        %(CompleteAccDeclare)s
119    };
120}};
121
122def template EACompDeclare {{
123    Fault
124    eaComp(ExecContext *, Trace::InstRecord *) const;
125}};
126
127def template InitiateAccDeclare {{
128    Fault
129    initiateAcc(ExecContext *, Trace::InstRecord *) const;
130}};
131
132
133def template CompleteAccDeclare {{
134    Fault
135    completeAcc(PacketPtr, ExecContext *, Trace::InstRecord *) const;
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        %(offset_code)s;
144    }
145}};
146
147def template EACompExecute {{
148    Fault
149    %(class_name)s::eaComp(ExecContext *xc, Trace::InstRecord *traceData) const
150    {
151        Addr EA;
152        Fault fault = NoFault;
153
154        %(op_decl)s;
155        %(op_rd)s;
156        %(ea_code)s;
157
158        if (fault == NoFault) {
159            %(op_wb)s;
160            xc->setEA(EA);
161        }
162
163        return fault;
164    }
165}};
166
167let {{
168def LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
169        inst_flags, base_class, postacc_code='', decode_template=BasicDecode,
170        exec_template_base=''):
171    # Make sure flags are in lists (convert to lists if not).
172    mem_flags = makeList(mem_flags)
173    inst_flags = makeList(inst_flags)
174
175    iop = InstObjParams(name, Name, base_class,
176        {'offset_code': offset_code, 'ea_code': ea_code,
177         'memacc_code': memacc_code, 'postacc_code': postacc_code },
178        inst_flags)
179
180    if mem_flags:
181        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
182        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
183        iop.constructor += s
184
185    # select templates
186
187    fullExecTemplate = eval(exec_template_base + 'Execute')
188    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
189    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
190
191    # (header_output, decoder_output, decode_block, exec_output)
192    return (LoadStoreDeclare.subst(iop),
193        LoadStoreConstructor.subst(iop),
194        decode_template.subst(iop),
195        fullExecTemplate.subst(iop) +
196        EACompExecute.subst(iop) +
197        initiateAccTemplate.subst(iop) +
198        completeAccTemplate.subst(iop))
199}};
200
201def template LoadExecute {{
202    Fault
203    %(class_name)s::execute(
204        ExecContext *xc, Trace::InstRecord *traceData) const
205    {
206        Addr EA;
207        Fault fault = NoFault;
208
209        %(op_decl)s;
210        %(op_rd)s;
211        %(ea_code)s;
212
213        if (fault == NoFault) {
214            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
215            %(memacc_code)s;
216        }
217
218        if (fault == NoFault) {
219            %(op_wb)s;
220        }
221
222        return fault;
223    }
224}};
225
226def template LoadInitiateAcc {{
227    Fault
228    %(class_name)s::initiateAcc(ExecContext *xc,
229        Trace::InstRecord *traceData) const
230    {
231        Addr EA;
232        Fault fault = NoFault;
233
234        %(op_src_decl)s;
235        %(op_rd)s;
236        %(ea_code)s;
237
238        if (fault == NoFault) {
239            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
240        }
241
242        return fault;
243    }
244}};
245
246def template LoadCompleteAcc {{
247    Fault
248    %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
249        Trace::InstRecord *traceData) const
250    {
251        Fault fault = NoFault;
252
253        %(op_decl)s;
254        %(op_rd)s;
255
256        getMem(pkt, Mem, traceData);
257
258        if (fault == NoFault) {
259            %(memacc_code)s;
260        }
261
262        if (fault == NoFault) {
263            %(op_wb)s;
264        }
265
266        return fault;
267    }
268}};
269
270def template StoreExecute {{
271    Fault
272    %(class_name)s::execute(ExecContext *xc,
273        Trace::InstRecord *traceData) const
274    {
275        Addr EA;
276        Fault fault = NoFault;
277
278        %(op_decl)s;
279        %(op_rd)s;
280        %(ea_code)s;
281
282        if (fault == NoFault) {
283            %(memacc_code)s;
284        }
285
286        if (fault == NoFault) {
287            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
288                nullptr);
289        }
290
291        if (fault == NoFault) {
292            %(postacc_code)s;
293        }
294
295        if (fault == NoFault) {
296            %(op_wb)s;
297        }
298
299        return fault;
300    }
301}};
302
303def template StoreInitiateAcc {{
304    Fault
305    %(class_name)s::initiateAcc(ExecContext *xc,
306        Trace::InstRecord *traceData) const
307    {
308        Addr EA;
309        Fault fault = NoFault;
310
311        %(op_decl)s;
312        %(op_rd)s;
313        %(ea_code)s;
314
315        if (fault == NoFault) {
316            %(memacc_code)s;
317        }
318
319        if (fault == NoFault) {
320            fault = writeMemTiming(xc, traceData, Mem, EA,
321                memAccessFlags, nullptr);
322        }
323
324        if (fault == NoFault) {
325            %(op_wb)s;
326        }
327
328        return fault;
329    }
330}};
331
332def template StoreCompleteAcc {{
333    Fault
334    %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
335        Trace::InstRecord *traceData) const
336    {
337        return NoFault;
338    }
339}};
340
341def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[],
342        inst_flags=[]) {{
343    offset_code = """
344                    ldisp = IMM12;
345                    if (IMMSIGN > 0)
346                        ldisp |= ~((uint64_t)0xFFF);
347                  """
348    (header_output, decoder_output, decode_block, exec_output) = \
349        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
350        inst_flags, 'Load', exec_template_base='Load')
351}};
352
353def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[],
354        inst_flags=[]) {{
355    offset_code = """
356                    sdisp = IMM5 | (IMM7 << 5);
357                    if (IMMSIGN > 0)
358                        sdisp |= ~((uint64_t)0xFFF);
359                  """
360    (header_output, decoder_output, decode_block, exec_output) = \
361        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
362        inst_flags, 'Store', exec_template_base='Store')
363}};
364