arch-riscv: Stop "using namespace std"
[gem5.git] / src / arch / riscv / isa / formats / standard.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2015 RISC-V Foundation
4 // Copyright (c) 2016-2017 The University of Virginia
5 // Copyright (c) 2020 Barkhausen Institut
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met: redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer;
12 // redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution;
15 // neither the name of the copyright holders nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 ////////////////////////////////////////////////////////////////////
32 //
33 // Integer instructions
34 //
35
36 def template ImmDeclare {{
37 //
38 // Static instruction class for "%(mnemonic)s".
39 //
40 class %(class_name)s : public %(base_class)s
41 {
42 private:
43 %(reg_idx_arr_decl)s;
44
45 public:
46 /// Constructor.
47 %(class_name)s(MachInst machInst);
48 Fault execute(ExecContext *, Trace::InstRecord *) const override;
49 std::string generateDisassembly(Addr pc,
50 const Loader::SymbolTable *symtab) const override;
51 };
52 }};
53
54 def template ImmConstructor {{
55 %(class_name)s::%(class_name)s(MachInst machInst)
56 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
57 {
58 %(set_reg_idx_arr)s;
59 %(constructor)s;
60 %(imm_code)s;
61 }
62 }};
63
64 def template ImmExecute {{
65 Fault
66 %(class_name)s::execute(
67 ExecContext *xc, Trace::InstRecord *traceData) const
68 {
69 Fault fault = NoFault;
70
71 %(op_decl)s;
72 %(op_rd)s;
73 if (fault == NoFault) {
74 %(code)s;
75 if (fault == NoFault) {
76 %(op_wb)s;
77 }
78 }
79 return fault;
80 }
81
82 std::string
83 %(class_name)s::generateDisassembly(Addr pc,
84 const Loader::SymbolTable *symtab) const
85 {
86 std::vector<RegId> indices = {%(regs)s};
87 std::stringstream ss;
88 ss << mnemonic << ' ';
89 for (const RegId& idx: indices)
90 ss << registerName(idx) << ", ";
91 ss << imm;
92 return ss.str();
93 }
94 }};
95
96 def template CILuiExecute {{
97 Fault
98 %(class_name)s::execute(
99 ExecContext *xc, Trace::InstRecord *traceData) const
100 {
101 Fault fault = NoFault;
102
103 %(op_decl)s;
104 %(op_rd)s;
105 if (fault == NoFault) {
106 %(code)s;
107 if (fault == NoFault) {
108 %(op_wb)s;
109 }
110 }
111 return fault;
112 }
113
114 std::string
115 %(class_name)s::generateDisassembly(Addr pc,
116 const Loader::SymbolTable *symtab) const
117 {
118 std::vector<RegId> indices = {%(regs)s};
119 std::stringstream ss;
120 ss << mnemonic << ' ';
121 for (const RegId& idx: indices)
122 ss << registerName(idx) << ", ";
123 // To be compliant with GCC, the immediate is formated to a 20-bit
124 // signed integer.
125 ss << ((((uint64_t)imm) >> 12) & 0xFFFFF);
126 return ss.str();
127 }
128 }};
129
130 def template FenceExecute {{
131 Fault
132 %(class_name)s::execute(
133 ExecContext *xc, Trace::InstRecord *traceData) const
134 {
135 Fault fault = NoFault;
136
137 %(op_decl)s;
138 %(op_rd)s;
139 if (fault == NoFault) {
140 %(code)s;
141 if (fault == NoFault) {
142 %(op_wb)s;
143 }
144 }
145 return fault;
146 }
147
148 std::string
149 %(class_name)s::generateDisassembly(Addr pc,
150 const Loader::SymbolTable *symtab) const
151 {
152 std::stringstream ss;
153 ss << mnemonic;
154 if (!FUNCT3) {
155 ss << ' ';
156 if (PRED & 0x8)
157 ss << 'i';
158 if (PRED & 0x4)
159 ss << 'o';
160 if (PRED & 0x2)
161 ss << 'r';
162 if (PRED & 0x1)
163 ss << 'w';
164 ss << ", ";
165 if (SUCC & 0x8)
166 ss << 'i';
167 if (SUCC & 0x4)
168 ss << 'o';
169 if (SUCC & 0x2)
170 ss << 'r';
171 if (SUCC & 0x1)
172 ss << 'w';
173 }
174 return ss.str();
175 }
176 }};
177
178 def template BranchDeclare {{
179 //
180 // Static instruction class for "%(mnemonic)s".
181 //
182 class %(class_name)s : public %(base_class)s
183 {
184 private:
185 %(reg_idx_arr_decl)s;
186
187 public:
188 /// Constructor.
189 %(class_name)s(MachInst machInst);
190 Fault execute(ExecContext *, Trace::InstRecord *) const override;
191
192 std::string
193 generateDisassembly(
194 Addr pc, const Loader::SymbolTable *symtab) const override;
195
196 RiscvISA::PCState
197 branchTarget(const RiscvISA::PCState &branchPC) const override;
198
199 using StaticInst::branchTarget;
200 };
201 }};
202
203 def template BranchExecute {{
204 Fault
205 %(class_name)s::execute(ExecContext *xc,
206 Trace::InstRecord *traceData) const
207 {
208 Fault fault = NoFault;
209
210 %(op_decl)s;
211 %(op_rd)s;
212 if (fault == NoFault) {
213 %(code)s;
214 if (fault == NoFault) {
215 %(op_wb)s;
216 }
217 }
218 return fault;
219 }
220
221 RiscvISA::PCState
222 %(class_name)s::branchTarget(const RiscvISA::PCState &branchPC) const
223 {
224 return branchPC.pc() + imm;
225 }
226
227 std::string
228 %(class_name)s::generateDisassembly(
229 Addr pc, const Loader::SymbolTable *symtab) const
230 {
231 std::vector<RegId> indices = {%(regs)s};
232 std::stringstream ss;
233 ss << mnemonic << ' ';
234 for (const RegId& idx: indices)
235 ss << registerName(idx) << ", ";
236 ss << imm;
237 return ss.str();
238 }
239 }};
240
241 def template JumpDeclare {{
242 //
243 // Static instruction class for "%(mnemonic)s".
244 //
245 class %(class_name)s : public %(base_class)s
246 {
247 private:
248 %(reg_idx_arr_decl)s;
249
250 public:
251 /// Constructor.
252 %(class_name)s(MachInst machInst);
253 Fault execute(ExecContext *, Trace::InstRecord *) const override;
254
255 std::string
256 generateDisassembly(
257 Addr pc, const Loader::SymbolTable *symtab) const override;
258
259 RiscvISA::PCState
260 branchTarget(ThreadContext *tc) const override;
261
262 using StaticInst::branchTarget;
263 };
264 }};
265
266 def template JumpExecute {{
267 Fault
268 %(class_name)s::execute(
269 ExecContext *xc, Trace::InstRecord *traceData) const
270 {
271 Fault fault = NoFault;
272
273 %(op_decl)s;
274 %(op_rd)s;
275 if (fault == NoFault) {
276 %(code)s;
277 if (fault == NoFault) {
278 %(op_wb)s;
279 }
280 }
281 return fault;
282 }
283
284 RiscvISA::PCState
285 %(class_name)s::branchTarget(ThreadContext *tc) const
286 {
287 PCState pc = tc->pcState();
288 pc.set((tc->readIntReg(srcRegIdx(0).index()) + imm)&~0x1);
289 return pc;
290 }
291
292 std::string
293 %(class_name)s::generateDisassembly(
294 Addr pc, const Loader::SymbolTable *symtab) const
295 {
296 std::stringstream ss;
297 ss << mnemonic << ' ';
298 if (QUADRANT == 0x3)
299 ss << registerName(destRegIdx(0)) << ", "
300 << imm << "(" << registerName(srcRegIdx(0)) << ")";
301 else
302 ss << registerName(srcRegIdx(0));
303 return ss.str();
304 }
305 }};
306
307 def template CSRExecute {{
308 Fault
309 %(class_name)s::execute(ExecContext *xc,
310 Trace::InstRecord *traceData) const
311 {
312 Fault fault = NoFault;
313
314 %(op_decl)s;
315 %(op_rd)s;
316
317 RegVal data, olddata;
318 switch (csr) {
319 case CSR_FCSR:
320 olddata = xc->readMiscReg(MISCREG_FFLAGS) |
321 (xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
322 break;
323 case CSR_SATP: {
324 auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
325 STATUS status = xc->readMiscReg(MISCREG_STATUS);
326 if (pm == PRV_U || (pm == PRV_S && status.tvm == 1)) {
327 std::string error = csprintf(
328 "SATP access in user mode or with TVM enabled\n");
329 fault = std::make_shared<IllegalInstFault>(error, machInst);
330 olddata = 0;
331 } else {
332 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
333 }
334 break;
335 }
336 case CSR_MSTATUS: {
337 auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
338 if (pm != PrivilegeMode::PRV_M) {
339 std::string error = csprintf(
340 "MSTATUS is only accessibly in machine mode\n");
341 fault = std::make_shared<IllegalInstFault>(error, machInst);
342 olddata = 0;
343 } else {
344 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
345 }
346 break;
347 }
348 default:
349 if (CSRData.find(csr) != CSRData.end()) {
350 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
351 } else {
352 std::string error = csprintf("Illegal CSR index %#x\n", csr);
353 fault = std::make_shared<IllegalInstFault>(error, machInst);
354 olddata = 0;
355 }
356 break;
357 }
358 auto mask = CSRMasks.find(csr);
359 if (mask != CSRMasks.end())
360 olddata &= mask->second;
361 DPRINTF(RiscvMisc, "Reading CSR %s: %#x\n", CSRData.at(csr).name,
362 olddata);
363 data = olddata;
364
365 if (fault == NoFault) {
366 %(code)s;
367 if (fault == NoFault) {
368 if (mask != CSRMasks.end())
369 data &= mask->second;
370 if (data != olddata) {
371 if (bits(csr, 11, 10) == 0x3) {
372 std::string error = csprintf("CSR %s is read-only\n",
373 CSRData.at(csr).name);
374 fault = std::make_shared<IllegalInstFault>(
375 error, machInst);
376 } else {
377 DPRINTF(RiscvMisc, "Writing %#x to CSR %s.\n", data,
378 CSRData.at(csr).name);
379 INTERRUPT oldinterrupt = olddata;
380 INTERRUPT newinterrupt = data;
381 switch (csr) {
382 case CSR_FCSR:
383 xc->setMiscReg(MISCREG_FFLAGS, bits(data, 4, 0));
384 xc->setMiscReg(MISCREG_FRM, bits(data, 7, 5));
385 break;
386 case CSR_MIP: case CSR_MIE:
387 if (oldinterrupt.mei != newinterrupt.mei ||
388 oldinterrupt.mti != newinterrupt.mti ||
389 oldinterrupt.msi != newinterrupt.msi) {
390 xc->setMiscReg(CSRData.at(csr).physIndex,data);
391 } else {
392 std::string error = "Interrupt m bits are "
393 "read-only\n";
394 fault = std::make_shared<IllegalInstFault>(
395 error, machInst);
396 }
397 break;
398 default:
399 xc->setMiscReg(CSRData.at(csr).physIndex, data);
400 break;
401 }
402 }
403 }
404 }
405 if (fault == NoFault) {
406 %(op_wb)s;
407 }
408 }
409 return fault;
410 }
411 }};
412
413 def format ROp(code, *opt_flags) {{
414 iop = InstObjParams(name, Name, 'RegOp', code, opt_flags)
415 header_output = BasicDeclare.subst(iop)
416 decoder_output = BasicConstructor.subst(iop)
417 decode_block = BasicDecode.subst(iop)
418 exec_output = BasicExecute.subst(iop)
419 }};
420
421 def format IOp(code, imm_type='int64_t', imm_code='imm = sext<12>(IMM12);',
422 *opt_flags) {{
423 regs = ['destRegIdx(0)','srcRegIdx(0)']
424 iop = InstObjParams(name, Name, 'ImmOp<%s>' % imm_type,
425 {'imm_code': imm_code, 'code': code,
426 'regs': ','.join(regs)}, opt_flags)
427 header_output = ImmDeclare.subst(iop)
428 decoder_output = ImmConstructor.subst(iop)
429 decode_block = BasicDecode.subst(iop)
430 exec_output = ImmExecute.subst(iop)
431 }};
432
433 def format FenceOp(code, imm_type='int64_t', *opt_flags) {{
434 regs = ['destRegIdx(0)','srcRegIdx(0)']
435 iop = InstObjParams(name, Name, 'ImmOp<%s>' % imm_type,
436 {'code': code, 'imm_code': 'imm = sext<12>(IMM12);',
437 'regs': ','.join(regs)}, opt_flags)
438 header_output = ImmDeclare.subst(iop)
439 decoder_output = ImmConstructor.subst(iop)
440 decode_block = BasicDecode.subst(iop)
441 exec_output = FenceExecute.subst(iop)
442 }};
443
444 def format BOp(code, *opt_flags) {{
445 imm_code = """
446 imm = BIMM12BITS4TO1 << 1 |
447 BIMM12BITS10TO5 << 5 |
448 BIMM12BIT11 << 11 |
449 IMMSIGN << 12;
450 imm = sext<13>(imm);
451 """
452 regs = ['srcRegIdx(0)','srcRegIdx(1)']
453 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
454 {'code': code, 'imm_code': imm_code,
455 'regs': ','.join(regs)}, opt_flags)
456 header_output = BranchDeclare.subst(iop)
457 decoder_output = ImmConstructor.subst(iop)
458 decode_block = BasicDecode.subst(iop)
459 exec_output = BranchExecute.subst(iop)
460 }};
461
462 def format Jump(code, *opt_flags) {{
463 regs = ['srcRegIdx(0)']
464 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
465 {'code': code, 'imm_code': 'imm = sext<12>(IMM12);',
466 'regs': ','.join(regs)}, opt_flags)
467 header_output = JumpDeclare.subst(iop)
468 decoder_output = ImmConstructor.subst(iop)
469 decode_block = BasicDecode.subst(iop)
470 exec_output = JumpExecute.subst(iop)
471 }};
472
473 def format UOp(code, *opt_flags) {{
474 regs = ['destRegIdx(0)']
475 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
476 {'code': code, 'imm_code': 'imm = IMM20;',
477 'regs': ','.join(regs)}, opt_flags)
478 header_output = ImmDeclare.subst(iop)
479 decoder_output = ImmConstructor.subst(iop)
480 decode_block = BasicDecode.subst(iop)
481 exec_output = ImmExecute.subst(iop)
482 }};
483
484 def format JOp(code, *opt_flags) {{
485 imm_code = """
486 imm = UJIMMBITS10TO1 << 1 |
487 UJIMMBIT11 << 11 |
488 UJIMMBITS19TO12 << 12 |
489 IMMSIGN << 20;
490 imm = sext<21>(imm);
491 """
492 pc = 'pc.set(pc.pc() + imm);'
493 regs = ['destRegIdx(0)']
494 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
495 {'code': code, 'imm_code': imm_code,
496 'regs': ','.join(regs)}, opt_flags)
497 header_output = BranchDeclare.subst(iop)
498 decoder_output = ImmConstructor.subst(iop)
499 decode_block = BasicDecode.subst(iop)
500 exec_output = BranchExecute.subst(iop)
501 }};
502
503 def format SystemOp(code, *opt_flags) {{
504 iop = InstObjParams(name, Name, 'SystemOp', code, opt_flags)
505 header_output = BasicDeclare.subst(iop)
506 decoder_output = BasicConstructor.subst(iop)
507 decode_block = BasicDecode.subst(iop)
508 exec_output = BasicExecute.subst(iop)
509 }};
510
511 def format CSROp(code, *opt_flags) {{
512 iop = InstObjParams(name, Name, 'CSROp', code, opt_flags)
513 header_output = BasicDeclare.subst(iop)
514 decoder_output = BasicConstructor.subst(iop)
515 decode_block = BasicDecode.subst(iop)
516 exec_output = CSRExecute.subst(iop)
517 }};