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(0)
53 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
56 class Store : public RiscvStaticInst
59 /// Displacement for EA calculation (signed).
63 /// Memory request flags. See mem_req_base.hh.
64 Request::Flags memAccessFlags;
67 Store(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
68 : RiscvStaticInst(mnem, _machInst, __opClass), sdisp(0)
70 sdisp = IMM5 | (IMM7 << 5);
72 sdisp |= ~((uint64_t)0xFFF);
76 generateDisassembly(Addr pc, const SymbolTable *symtab) const;
84 Load::generateDisassembly(Addr pc, const SymbolTable *symtab) const
87 ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", " <<
88 ldisp << '(' << registerName(_srcRegIdx[0]) << ')';
93 Store::generateDisassembly(Addr pc, const SymbolTable *symtab) const
96 ss << mnemonic << ' ' << registerName(_srcRegIdx[1]) << ", " <<
97 sdisp << '(' << registerName(_srcRegIdx[0]) << ')';
102 def template LoadStoreDeclare {{
104 * Static instruction class for "%(mnemonic)s".
106 class %(class_name)s : public %(base_class)s
110 %(class_name)s(ExtMachInst machInst);
116 %(InitiateAccDeclare)s
118 %(CompleteAccDeclare)s
122 def template EACompDeclare {{
124 eaComp(%(CPU_exec_context)s *, Trace::InstRecord *) const;
127 def template InitiateAccDeclare {{
129 initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
133 def template CompleteAccDeclare {{
135 completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
138 def template LoadStoreConstructor {{
139 %(class_name)s::%(class_name)s(ExtMachInst machInst):
140 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
147 def template EACompExecute {{
149 %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
150 Trace::InstRecord *traceData) const
153 Fault fault = NoFault;
159 if (fault == NoFault) {
169 def 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)
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 },
182 mem_flags = [ 'Request::%s' % flag for flag in mem_flags ]
183 s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
188 fullExecTemplate = eval(exec_template_base + 'Execute')
189 initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
190 completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
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))
202 def template LoadExecute {{
204 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
205 Trace::InstRecord *traceData) const
208 Fault fault = NoFault;
214 if (fault == NoFault) {
215 fault = readMemAtomic(xc, traceData, EA, Mem, memAccessFlags);
219 if (fault == NoFault) {
227 def template LoadInitiateAcc {{
229 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
230 Trace::InstRecord *traceData) const
233 Fault fault = NoFault;
239 if (fault == NoFault) {
240 fault = initiateMemRead(xc, traceData, EA, Mem, memAccessFlags);
247 def template LoadCompleteAcc {{
249 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
250 Trace::InstRecord *traceData) const
252 Fault fault = NoFault;
257 getMem(pkt, Mem, traceData);
259 if (fault == NoFault) {
263 if (fault == NoFault) {
271 def template StoreExecute {{
273 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
274 Trace::InstRecord *traceData) const
277 Fault fault = NoFault;
283 if (fault == NoFault) {
287 if (fault == NoFault) {
288 fault = writeMemAtomic(xc, traceData, Mem, EA, memAccessFlags,
292 if (fault == NoFault) {
296 if (fault == NoFault) {
304 def template StoreInitiateAcc {{
306 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
307 Trace::InstRecord *traceData) const
310 Fault fault = NoFault;
316 if (fault == NoFault) {
320 if (fault == NoFault) {
321 fault = writeMemTiming(xc, traceData, Mem, EA,
322 memAccessFlags, nullptr);
325 if (fault == NoFault) {
333 def template StoreCompleteAcc {{
335 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
336 Trace::InstRecord *traceData) const
342 def format Load(memacc_code, ea_code = {{EA = Rs1 + ldisp;}}, mem_flags=[],
347 ldisp |= ~((uint64_t)0xFFF);
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')
354 def format Store(memacc_code, ea_code={{EA = Rs1 + sdisp;}}, mem_flags=[],
357 sdisp = IMM5 | (IMM7 << 5);
359 sdisp |= ~((uint64_t)0xFFF);
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')