// -*- mode:c++ -*- // Copyright (c) 2015 RISC-V Foundation // Copyright (c) 2016 The University of Virginia // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Alec Roelke //////////////////////////////////////////////////////////////////// // // Integer instructions // output header {{ #include /** * Base class for R-type operations */ class ROp : public RiscvStaticInst { protected: /// Constructor ROp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass) {} std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Base class for I-type operations */ class IOp : public RiscvStaticInst { protected: int64_t imm; /// Constructor IOp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass),imm(IMM12) { if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF); } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Class for jalr instructions */ class Jump : public IOp { protected: Jump(const char *mnem, MachInst _machInst, OpClass __opClass) : IOp(mnem, _machInst, __opClass) {} RiscvISA::PCState branchTarget(ThreadContext *tc) const; using StaticInst::branchTarget; using IOp::generateDisassembly; }; /** * Base class for S-type operations */ class SOp : public RiscvStaticInst { protected: int64_t imm; /// Constructor SOp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass),imm(0) { imm |= IMM5; imm |= IMM7 << 5; if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF); } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Base class for SB-type operations */ class SBOp : public RiscvStaticInst { protected: int64_t imm; /// Constructor SBOp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass),imm(0) { imm |= BIMM12BIT11 << 11; imm |= BIMM12BITS4TO1 << 1; imm |= BIMM12BITS10TO5 << 5; if (IMMSIGN > 0) imm |= ~((uint64_t)0xFFF); } RiscvISA::PCState branchTarget(const RiscvISA::PCState &branchPC) const; using StaticInst::branchTarget; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Base class for U-type operations */ class UOp : public RiscvStaticInst { protected: int64_t imm; /// Constructor UOp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass), imm(0) { int32_t temp = IMM20 << 12; imm = temp; } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Base class for UJ-type operations */ class UJOp : public RiscvStaticInst { protected: int64_t imm; /// Constructor UJOp(const char *mnem, MachInst _machInst, OpClass __opClass) : RiscvStaticInst(mnem, _machInst, __opClass),imm(0) { imm |= UJIMMBITS19TO12 << 12; imm |= UJIMMBIT11 << 11; imm |= UJIMMBITS10TO1 << 1; if (IMMSIGN > 0) imm |= ~((uint64_t)0xFFFFF); } RiscvISA::PCState branchTarget(const RiscvISA::PCState &branchPC) const; using StaticInst::branchTarget; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; }}; //Outputs to decoder.cc output decoder {{ std::string ROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << regName(_srcRegIdx[0]) << ", " << regName(_srcRegIdx[1]); return ss.str(); } std::string IOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << regName(_srcRegIdx[0]) << ", " << imm; return ss.str(); } RiscvISA::PCState Jump::branchTarget(ThreadContext *tc) const { PCState pc = tc->pcState(); IntReg Rs1 = tc->readIntReg(_srcRegIdx[0]); pc.set((Rs1 + imm)&~0x1); return pc; } std::string SOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_srcRegIdx[1]) << ", " << imm << '(' << regName(_srcRegIdx[0]) << ')'; return ss.str(); } RiscvISA::PCState SBOp::branchTarget(const RiscvISA::PCState &branchPC) const { return branchPC.pc() + imm; } std::string SBOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_srcRegIdx[0]) << ", " << regName(_srcRegIdx[1]) << ", " << imm; return ss.str(); } std::string UOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << imm; return ss.str(); } RiscvISA::PCState UJOp::branchTarget(const RiscvISA::PCState &branchPC) const { return branchPC.pc() + imm; } std::string UJOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; ss << mnemonic << ' ' << regName(_destRegIdx[0]) << ", " << imm; return ss.str(); } }}; def format ROp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'ROp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format IOp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'IOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format Jump(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'Jump', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format SOp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'SOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format SBOp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'SBOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format UOp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'UOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; def format UJOp(code, *opt_flags) {{ iop = InstObjParams(name, Name, 'UJOp', code, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }};