mem.isa (12120:133620bfc43b) mem.isa (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
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;
124 eaComp(ExecContext *, Trace::InstRecord *) const;
125}};
126
127def template InitiateAccDeclare {{
128 Fault
125}};
126
127def template InitiateAccDeclare {{
128 Fault
129 initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
129 initiateAcc(ExecContext *, Trace::InstRecord *) const;
130}};
131
132
133def template CompleteAccDeclare {{
134 Fault
130}};
131
132
133def template CompleteAccDeclare {{
134 Fault
135 completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
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
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
149 %(class_name)s::eaComp(ExecContext *xc, 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
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
204 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
205 Trace::InstRecord *traceData) const
203 %(class_name)s::execute(
204 ExecContext *xc, 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
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
229 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
228 %(class_name)s::initiateAcc(ExecContext *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
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
249 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
248 %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *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
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
273 %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
272 %(class_name)s::execute(ExecContext *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
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
306 %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
305 %(class_name)s::initiateAcc(ExecContext *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
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
335 %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
334 %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *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}};
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}};