mem.isa revision 12120:133620bfc43b
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(%(CPU_exec_context)s *, Trace::InstRecord *) const;
125}};
126
127def template InitiateAccDeclare {{
128    Fault
129    initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
130}};
131
132
133def template CompleteAccDeclare {{
134    Fault
135    completeAcc(PacketPtr, %(CPU_exec_context)s *, 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(CPU_EXEC_CONTEXT *xc,
150        Trace::InstRecord *traceData) const
151    {
152        Addr EA;
153        Fault fault = NoFault;
154
155        %(op_decl)s;
156        %(op_rd)s;
157        %(ea_code)s;
158
159        if (fault == NoFault) {
160            %(op_wb)s;
161            xc->setEA(EA);
162        }
163
164        return fault;
165    }
166}};
167
168let {{
169def LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
170        inst_flags, base_class, postacc_code='', decode_template=BasicDecode,
171        exec_template_base=''):
172    # Make sure flags are in lists (convert to lists if not).
173    mem_flags = makeList(mem_flags)
174    inst_flags = makeList(inst_flags)
175
176    iop = InstObjParams(name, Name, base_class,
177        {'offset_code': offset_code, 'ea_code': ea_code,
178         'memacc_code': memacc_code, 'postacc_code': postacc_code },
179        inst_flags)
180
181    if mem_flags:
182        mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
183        s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
184        iop.constructor += s
185
186    # select templates
187
188    fullExecTemplate = eval(exec_template_base + 'Execute')
189    initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
190    completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
191
192    # (header_output, decoder_output, decode_block, exec_output)
193    return (LoadStoreDeclare.subst(iop),
194        LoadStoreConstructor.subst(iop),
195        decode_template.subst(iop),
196        fullExecTemplate.subst(iop) +
197        EACompExecute.subst(iop) +
198        initiateAccTemplate.subst(iop) +
199        completeAccTemplate.subst(iop))
200}};
201
202def template LoadExecute {{
203    Fault
204    %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
205        Trace::InstRecord *traceData) const
206    {
207        Addr EA;
208        Fault fault = NoFault;
209
210        %(op_decl)s;
211        %(op_rd)s;
212        %(ea_code)s;
213
214        if (fault == NoFault) {
215            fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
216            %(memacc_code)s;
217        }
218
219        if (fault == NoFault) {
220            %(op_wb)s;
221        }
222
223        return fault;
224    }
225}};
226
227def template LoadInitiateAcc {{
228    Fault
229    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
230        Trace::InstRecord *traceData) const
231    {
232        Addr EA;
233        Fault fault = NoFault;
234
235        %(op_src_decl)s;
236        %(op_rd)s;
237        %(ea_code)s;
238
239        if (fault == NoFault) {
240            fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
241        }
242
243        return fault;
244    }
245}};
246
247def template LoadCompleteAcc {{
248    Fault
249    %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
250        Trace::InstRecord *traceData) const
251    {
252        Fault fault = NoFault;
253
254        %(op_decl)s;
255        %(op_rd)s;
256
257        getMem(pkt, Mem, traceData);
258
259        if (fault == NoFault) {
260            %(memacc_code)s;
261        }
262
263        if (fault == NoFault) {
264            %(op_wb)s;
265        }
266
267        return fault;
268    }
269}};
270
271def template StoreExecute {{
272    Fault
273    %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
274        Trace::InstRecord *traceData) const
275    {
276        Addr EA;
277        Fault fault = NoFault;
278
279        %(op_decl)s;
280        %(op_rd)s;
281        %(ea_code)s;
282
283        if (fault == NoFault) {
284            %(memacc_code)s;
285        }
286
287        if (fault == NoFault) {
288            fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
289                nullptr);
290        }
291
292        if (fault == NoFault) {
293            %(postacc_code)s;
294        }
295
296        if (fault == NoFault) {
297            %(op_wb)s;
298        }
299
300        return fault;
301    }
302}};
303
304def template StoreInitiateAcc {{
305    Fault
306    %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
307        Trace::InstRecord *traceData) const
308    {
309        Addr EA;
310        Fault fault = NoFault;
311
312        %(op_decl)s;
313        %(op_rd)s;
314        %(ea_code)s;
315
316        if (fault == NoFault) {
317            %(memacc_code)s;
318        }
319
320        if (fault == NoFault) {
321            fault = writeMemTiming(xc, traceData, Mem, EA,
322                memAccessFlags, nullptr);
323        }
324
325        if (fault == NoFault) {
326            %(op_wb)s;
327        }
328
329        return fault;
330    }
331}};
332
333def template StoreCompleteAcc {{
334    Fault
335    %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
336        Trace::InstRecord *traceData) const
337    {
338        return NoFault;
339    }
340}};
341
342def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[],
343        inst_flags=[]) {{
344    offset_code = """
345                    ldisp = IMM12;
346                    if (IMMSIGN > 0)
347                        ldisp |= ~((uint64_t)0xFFF);
348                  """
349    (header_output, decoder_output, decode_block, exec_output) = \
350        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
351        inst_flags, 'Load', exec_template_base='Load')
352}};
353
354def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[],
355        inst_flags=[]) {{
356    offset_code = """
357                    sdisp = IMM5 | (IMM7 << 5);
358                    if (IMMSIGN > 0)
359                        sdisp |= ~((uint64_t)0xFFF);
360                  """
361    (header_output, decoder_output, decode_block, exec_output) = \
362        LoadStoreBase(name, Name, offset_code, ea_code, memacc_code, mem_flags,
363        inst_flags, 'Store', exec_template_base='Store')
364}};
365