3 // Copyright (c) 2015 RISC-V Foundation
4 // Copyright (c) 2016 The University of Virginia
5 // All rights reserved.
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.
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.
30 // Authors: Alec Roelke
32 ////////////////////////////////////////////////////////////////////
34 // Memory operation instructions
37 class Load : public RiscvStaticInst
40 /// Displacement for EA calculation (signed).
44 /// Memory request flags. See mem_req_base.hh.
45 Request::Flags memAccessFlags;
48 Load(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
49 : RiscvStaticInst(mnem, _machInst, __opClass), ldisp(IMM12)
52 ldisp |= ~((uint64_t)0xFFF);
56 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
59 class Store : public RiscvStaticInst
62 /// Displacement for EA calculation (signed).
66 /// Memory request flags. See mem_req_base.hh.
67 Request::Flags memAccessFlags;
70 Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
71 : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(IMM5)
75 sdisp |= ~((uint64_t)0xFFF);
79 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
87 Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const
90 ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << ldisp <<
91 '(' << regName(_srcRegIdx[0]) << ')';
96 Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const
99 ss << mnemonic << ' ' << regName(_srcRegIdx[1]) << ", " << sdisp <<
100 '(' << regName(_srcRegIdx[0]) << ')';
105 def template LoadStoreDeclare {{
107 * Static instruction class for "%(mnemonic)s".
109 class %(class_name)s : public %(base_class)s
113 %(class_name)s(ExtMachInst machInst);
119 %(InitiateAccDeclare)s
121 %(CompleteAccDeclare)s
125 def template EACompDeclare {{
127 eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
130 def template InitiateAccDeclare {{
132 initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
136 def template CompleteAccDeclare {{
138 completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
141 def template LoadStoreConstructor {{
142 %(class_name)s::%(class_name)s(ExtMachInst machInst):
143 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
149 def template EACompExecute {{
151 %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
152 Trace::InstRecord *traceData) const
155 Fault fault = NoFault;
161 if (fault == NoFault) {
171 def 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']
178 iop = InstObjParams(name, Name, base_class,
179 { 'ea_code':ea_code, 'memacc_code':memacc_code,
180 'postacc_code':postacc_code }, inst_flags)
183 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
184 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
189 # The InitiateAcc template is the same for StoreCond templates as the
190 # corresponding Store template..
191 StoreCondInitiateAcc = StoreInitiateAcc
193 fullExecTemplate = eval(exec_template_base + 'Execute')
194 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
195 completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
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))
207 def template LoadExecute {{
209 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
210 Trace::InstRecord *traceData) const
213 Fault fault = NoFault;
219 if (fault == NoFault) {
220 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
224 if (fault == NoFault) {
232 def template LoadInitiateAcc {{
234 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
235 Trace::InstRecord *traceData) const
238 Fault fault = NoFault;
244 if (fault == NoFault) {
245 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
252 def template LoadCompleteAcc {{
254 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
255 Trace::InstRecord *traceData) const
257 Fault fault = NoFault;
262 getMem(pkt, Mem, traceData);
264 if (fault == NoFault) {
268 if (fault == NoFault) {
276 def template StoreExecute {{
278 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
279 Trace::InstRecord *traceData) const
282 Fault fault = NoFault;
288 if (fault == NoFault) {
292 if (fault == NoFault) {
293 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
297 if (fault == NoFault) {
301 if (fault == NoFault) {
309 def template StoreInitiateAcc {{
311 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
312 Trace::InstRecord *traceData) const
315 Fault fault = NoFault;
321 if (fault == NoFault) {
325 if (fault == NoFault) {
326 fault = writeMemTiming(xc, traceData, Mem, EA,
327 memAccessFlags, nullptr);
330 if (fault == NoFault) {
338 def template StoreCompleteAcc {{
340 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
341 Trace::InstRecord *traceData) const
347 def template StoreCondExecute {{
348 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
349 Trace::InstRecord *traceData) const
352 Fault fault = NoFault;
359 if (fault == NoFault) {
363 if (fault == NoFault) {
364 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
366 // RISC-V has the opposite convention gem5 has for success flags,
367 // so we invert the result here.
371 if (fault == NoFault) {
375 if (fault == NoFault) {
383 def template StoreCondCompleteAcc {{
384 Fault %(class_name)s::completeAcc(Packet *pkt, CPU_EXEC_CONTEXT *xc,
385 Trace::InstRecord *traceData) const
387 Fault fault = NoFault;
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();
395 if (fault == NoFault) {
399 if (fault == NoFault) {
407 def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_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')
414 def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_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')
421 def format StoreCond(memacc_code, postacc_code, ea_code={{EA = Rs1;}},
422 mem_flags=[], inst_flags=[], aq=0, rl=0) {{
424 mem_flags = makeList(mem_flags) + ["ACQUIRE"]
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')
432 def format LoadReserved(memacc_code, ea_code={{EA = Rs1;}}, mem_flags=[],
433 inst_flags=[], aq=0, rl=0) {{
435 mem_flags = makeList(mem_flags) + ["ACQUIRE"]
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')