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.
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.
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.
31 ////////////////////////////////////////////////////////////////////
33 // Integer instructions
36 def template ImmDeclare {{
38 // Static instruction class for "%(mnemonic)s".
40 class %(class_name)s : public %(base_class)s
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;
54 def template ImmConstructor {{
55 %(class_name)s::%(class_name)s(MachInst machInst)
56 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
64 def template ImmExecute {{
66 %(class_name)s::execute(
67 ExecContext *xc, Trace::InstRecord *traceData) const
69 Fault fault = NoFault;
73 if (fault == NoFault) {
75 if (fault == NoFault) {
83 %(class_name)s::generateDisassembly(Addr pc,
84 const Loader::SymbolTable *symtab) const
86 std::vector<RegId> indices = {%(regs)s};
88 ss << mnemonic << ' ';
89 for (const RegId& idx: indices)
90 ss << registerName(idx) << ", ";
96 def template CILuiExecute {{
98 %(class_name)s::execute(
99 ExecContext *xc, Trace::InstRecord *traceData) const
101 Fault fault = NoFault;
105 if (fault == NoFault) {
107 if (fault == NoFault) {
115 %(class_name)s::generateDisassembly(Addr pc,
116 const Loader::SymbolTable *symtab) const
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
125 ss << ((((uint64_t)imm) >> 12) & 0xFFFFF);
130 def template FenceExecute {{
132 %(class_name)s::execute(
133 ExecContext *xc, Trace::InstRecord *traceData) const
135 Fault fault = NoFault;
139 if (fault == NoFault) {
141 if (fault == NoFault) {
149 %(class_name)s::generateDisassembly(Addr pc,
150 const Loader::SymbolTable *symtab) const
152 std::stringstream ss;
178 def template BranchDeclare {{
180 // Static instruction class for "%(mnemonic)s".
182 class %(class_name)s : public %(base_class)s
185 %(reg_idx_arr_decl)s;
189 %(class_name)s(MachInst machInst);
190 Fault execute(ExecContext *, Trace::InstRecord *) const override;
194 Addr pc, const Loader::SymbolTable *symtab) const override;
197 branchTarget(const RiscvISA::PCState &branchPC) const override;
199 using StaticInst::branchTarget;
203 def template BranchExecute {{
205 %(class_name)s::execute(ExecContext *xc,
206 Trace::InstRecord *traceData) const
208 Fault fault = NoFault;
212 if (fault == NoFault) {
214 if (fault == NoFault) {
222 %(class_name)s::branchTarget(const RiscvISA::PCState &branchPC) const
224 return branchPC.pc() + imm;
228 %(class_name)s::generateDisassembly(
229 Addr pc, const Loader::SymbolTable *symtab) const
231 std::vector<RegId> indices = {%(regs)s};
232 std::stringstream ss;
233 ss << mnemonic << ' ';
234 for (const RegId& idx: indices)
235 ss << registerName(idx) << ", ";
241 def template JumpDeclare {{
243 // Static instruction class for "%(mnemonic)s".
245 class %(class_name)s : public %(base_class)s
248 %(reg_idx_arr_decl)s;
252 %(class_name)s(MachInst machInst);
253 Fault execute(ExecContext *, Trace::InstRecord *) const override;
257 Addr pc, const Loader::SymbolTable *symtab) const override;
260 branchTarget(ThreadContext *tc) const override;
262 using StaticInst::branchTarget;
266 def template JumpExecute {{
268 %(class_name)s::execute(
269 ExecContext *xc, Trace::InstRecord *traceData) const
271 Fault fault = NoFault;
275 if (fault == NoFault) {
277 if (fault == NoFault) {
285 %(class_name)s::branchTarget(ThreadContext *tc) const
287 PCState pc = tc->pcState();
288 pc.set((tc->readIntReg(srcRegIdx(0).index()) + imm)&~0x1);
293 %(class_name)s::generateDisassembly(
294 Addr pc, const Loader::SymbolTable *symtab) const
296 std::stringstream ss;
297 ss << mnemonic << ' ';
299 ss << registerName(destRegIdx(0)) << ", "
300 << imm << "(" << registerName(srcRegIdx(0)) << ")";
302 ss << registerName(srcRegIdx(0));
307 def template CSRExecute {{
309 %(class_name)s::execute(ExecContext *xc,
310 Trace::InstRecord *traceData) const
312 Fault fault = NoFault;
317 RegVal data, olddata;
320 olddata = xc->readMiscReg(MISCREG_FFLAGS) |
321 (xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
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);
332 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
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);
344 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
349 if (CSRData.find(csr) != CSRData.end()) {
350 olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
352 std::string error = csprintf("Illegal CSR index %#x\n", csr);
353 fault = std::make_shared<IllegalInstFault>(error, machInst);
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,
365 if (fault == NoFault) {
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>(
377 DPRINTF(RiscvMisc, "Writing %#x to CSR %s.\n", data,
378 CSRData.at(csr).name);
379 INTERRUPT oldinterrupt = olddata;
380 INTERRUPT newinterrupt = data;
383 xc->setMiscReg(MISCREG_FFLAGS, bits(data, 4, 0));
384 xc->setMiscReg(MISCREG_FRM, bits(data, 7, 5));
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);
392 std::string error = "Interrupt m bits are "
394 fault = std::make_shared<IllegalInstFault>(
399 xc->setMiscReg(CSRData.at(csr).physIndex, data);
405 if (fault == NoFault) {
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)
421 def format IOp(code, imm_type='int64_t', imm_code='imm = sext<12>(IMM12);',
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)
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)
444 def format BOp(code, *opt_flags) {{
446 imm = BIMM12BITS4TO1 << 1 |
447 BIMM12BITS10TO5 << 5 |
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)
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)
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)
484 def format JOp(code, *opt_flags) {{
486 imm = UJIMMBITS10TO1 << 1 |
488 UJIMMBITS19TO12 << 12 |
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)
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)
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)