diff --git a/src/arch/riscv/insts/SConscript b/src/arch/riscv/insts/SConscript index 2822cf86b4..2519b3e07d 100644 --- a/src/arch/riscv/insts/SConscript +++ b/src/arch/riscv/insts/SConscript @@ -34,3 +34,4 @@ Source('mem.cc', tags='riscv isa') Source('standard.cc', tags='riscv isa') Source('static_inst.cc', tags='riscv isa') Source('vector.cc', tags='riscv isa') +Source('zcmp.cc', tags='riscv isa') diff --git a/src/arch/riscv/insts/zcmp.cc b/src/arch/riscv/insts/zcmp.cc new file mode 100644 index 0000000000..018ea45a60 --- /dev/null +++ b/src/arch/riscv/insts/zcmp.cc @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 Google LLC + * 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. + */ + +#include "arch/riscv/insts/zcmp.hh" + +#include + +#include "arch/riscv/regs/int.hh" +#include "arch/riscv/utility.hh" + +namespace gem5 +{ + +namespace RiscvISA +{ + +CmMacroInst::CmMacroInst( + const char* mnem, ExtMachInst machInst, OpClass opClass) + : RiscvMacroInst(mnem, machInst, opClass), rlist(machInst.rlist) +{ +} + +// Ref: https://github.com/riscv-software-src/riscv-isa-sim/blob/f7d0dba60/ +// riscv/decode.h#L168 +uint64_t +CmMacroInst::stackAdj() const +{ + uint64_t stack_adj_base = 0; + switch (machInst.rlist) { + case 15: + stack_adj_base += 16; + [[fallthrough]]; + case 14: + if (machInst.rv_type == RV64) { + stack_adj_base += 16; + } + [[fallthrough]]; + case 13: + case 12: + stack_adj_base += 16; + [[fallthrough]]; + case 11: + case 10: + if (machInst.rv_type == RV64) { + stack_adj_base += 16; + } + [[fallthrough]]; + case 9: + case 8: + stack_adj_base += 16; + [[fallthrough]]; + case 7: + case 6: + if (machInst.rv_type == RV64) { + stack_adj_base += 16; + } + [[fallthrough]]; + case 5: + case 4: + stack_adj_base += 16; + break; + } + + return stack_adj_base + machInst.spimm * 16; +} + +std::string +CmMacroInst::getRlistStr() const +{ + std::string s = ""; + switch (machInst.rlist) { + case 15: + s = csprintf("{%s, %s-%s}", registerName(ReturnAddrReg), + registerName(int_reg::S0), + registerName(PushPopRegList[0])); + break; + case 14: + case 13: + case 12: + case 11: + case 10: + case 9: + case 8: + case 7: + case 6: + s = csprintf("{%s, %s-%s}", registerName(ReturnAddrReg), + registerName(int_reg::S0), + registerName(PushPopRegList[16-machInst.rlist])); + break; + case 5: + s = csprintf("{%s, %s}", registerName(ReturnAddrReg), + registerName(int_reg::S0)); + break; + case 4: + s = csprintf("{%s}", registerName(ReturnAddrReg)); + break; + default: + break; + } + + return s; +} + +} // namespace RiscvISA +} // namespace gem5 diff --git a/src/arch/riscv/insts/zcmp.hh b/src/arch/riscv/insts/zcmp.hh new file mode 100644 index 0000000000..5f0d734b10 --- /dev/null +++ b/src/arch/riscv/insts/zcmp.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Google LLC + * 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. + */ + +#ifndef __ARCH_RISCV_INSTS_ZCMP_HH__ +#define __ARCH_RISCV_INSTS_ZCMP_HH__ + +#include + +#include "arch/riscv/insts/static_inst.hh" +#include "cpu/static_inst.hh" + +namespace gem5 +{ + +namespace RiscvISA +{ + +class CmMacroInst : public RiscvMacroInst +{ + public: + CmMacroInst(const char* mnem, ExtMachInst machInst, OpClass opClass); + + protected: + using RiscvMacroInst::RiscvMacroInst; + + uint64_t stackAdj() const; + std::string getRlistStr() const; + + uint64_t rlist; +}; + +} // namespace RiscvISA +} // namespace gem5 + +#endif // __ARCH_RISCV_INSTS_ZCMP_HH__ diff --git a/src/arch/riscv/isa/bitfields.isa b/src/arch/riscv/isa/bitfields.isa index 4589184e68..5fc624acc1 100644 --- a/src/arch/riscv/isa/bitfields.isa +++ b/src/arch/riscv/isa/bitfields.isa @@ -104,10 +104,13 @@ def bitfield CFUNCT1 <12>; def bitfield CFUNCT1BIT6 <6>; def bitfield CFUNCT2HIGH <11:10>; def bitfield CFUNCT2LOW <6:5>; +def bitfield CFUNCT2MID <9:8>; def bitfield RC1 <11:7>; def bitfield RC2 <6:2>; def bitfield RP1 <9:7>; def bitfield RP2 <4:2>; +def bitfield R1S <9:7>; +def bitfield R2S <4:2>; def bitfield FC1 <11:7>; def bitfield FC2 <6:2>; def bitfield FP2 <4:2>; diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index db0e60cc77..90efb8ad82 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -487,6 +487,20 @@ decode QUADRANT default Unknown::unknown() { } format CompressedStore { 0x5: decode ENABLE_ZCD { + 0x0: decode CFUNCT6LOW3 { + 0x3: decode CFUNCT2LOW { + 0x1: CmMvsa01::cm_mvsa01(); + 0x3: CmMva01s::cm_mva01s(); + } + 0x6: decode CFUNCT2MID { + 0x0: CmPush::cm_push(); + 0x2: CmPop::cm_pop(); + } + 0x7: decode CFUNCT2MID { + 0x0: CmPop::cm_popretz(is_ret=True, has_a0=True); + 0x2: CmPop::cm_popret(is_ret=True); + } + } 0x1: c_fsdsp({{ offset = CIMM6<5:3> << 3 | CIMM6<2:0> << 6; diff --git a/src/arch/riscv/isa/formats/formats.isa b/src/arch/riscv/isa/formats/formats.isa index 0102df17d7..377bc5d061 100644 --- a/src/arch/riscv/isa/formats/formats.isa +++ b/src/arch/riscv/isa/formats/formats.isa @@ -40,6 +40,7 @@ ##include "vector_conf.isa" ##include "vector_arith.isa" ##include "vector_mem.isa" +##include "zcmp.isa" // Include formats for nonstandard extensions ##include "compressed.isa" diff --git a/src/arch/riscv/isa/formats/zcmp.isa b/src/arch/riscv/isa/formats/zcmp.isa new file mode 100644 index 0000000000..d8adbc5532 --- /dev/null +++ b/src/arch/riscv/isa/formats/zcmp.isa @@ -0,0 +1,772 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2015 RISC-V Foundation +// Copyright (c) 2016 The University of Virginia +// Copyright (c) 2024 Google LLC +// 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. + +// Cmpush template. +def template CmPushDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst); + + protected: + using %(base_class)s::%(base_class)s; + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; + }; +}}; + + +def template CmPushConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) : + %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + StaticInstPtr cur_inst = nullptr; + if (rlist < 4) { + cur_inst = new Unknown(machInst); + cur_inst->setFlag(IsMicroop); + microops.emplace_back(cur_inst); + } else { + int start_reg = 0; + if (rlist != 15) { + start_reg = (16-rlist); + } + + int offset = 0; + for (int i = start_reg; i < PushPopRegList.size(); i++) { + offset -= rvSelect(4, 8); + + if (machInst.rv_type == RV32) { + cur_inst = new %(class_name)s32MicroInst( + machInst, PushPopRegList[i], offset); + } else { + cur_inst = new %(class_name)s64MicroInst( + machInst, PushPopRegList[i], offset); + } + microops.emplace_back(cur_inst); + } + + cur_inst = new %(class_name)sSpAdjMicroInst(machInst, -stackAdj()); + microops.emplace_back(cur_inst); + } + + microops.front()->setFirstMicroop(); + microops.back()->setLastMicroop(); + } +}}; + +def template CmPushExecute {{ + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << getRlistStr() << ", " << (int64_t)-stackAdj(); + return ss.str(); + } +}}; + +def template CmStoreMicroDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegId push_reg, int64_t offset); + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc( + Packet *, ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly( + Addr, const loader::SymbolTable *) const override; + + protected: + using %(base_class)s::%(base_class)s; + + private: + %(reg_idx_arr_decl)s; + + int64_t offset; + Request::Flags memAccessFlags; + }; +}}; + +def template CmStoreMicroConstructor {{ + %(class_name)s::%(class_name)s( + ExtMachInst machInst, RegId push_reg, int64_t offset) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s), + offset(offset) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template CmStoreMicroExecute {{ + Fault + %(class_name)s::execute( + ExecContext *xc, trace::InstRecord *traceData) const + { + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + %(memacc_code)s; + + { + Fault fault = + writeMemAtomicLE(xc, traceData, Mem, EA, memAccessFlags, + nullptr); + if (fault != NoFault) + return fault; + } + + %(op_wb)s; + + return NoFault; + } + + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(1)) << ", " << + offset << '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); + } +}}; + +def template CmStoreMicroInitiateAcc {{ + Fault + %(class_name)s::initiateAcc(ExecContext *xc, + trace::InstRecord *traceData) const + { + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + %(memacc_code)s; + + { + Fault fault = writeMemTimingLE(xc, traceData, Mem, EA, + memAccessFlags, nullptr); + if (fault != NoFault) + return fault; + } + + %(op_wb)s; + + return NoFault; + } +}}; + +def template CmStoreMicroCompleteAcc {{ + Fault + %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const + { + return NoFault; + } +}}; + +def template SpAdjMicroDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, int64_t adj); + protected: + using %(base_class)s::%(base_class)s; + + Fault execute(ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly( + Addr, const loader::SymbolTable *) const override; + + private: + %(reg_idx_arr_decl)s; + + int64_t adj; + }; +}}; + +def template SpAdjMicroConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst, int64_t adj) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s), adj(adj) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template SpAdjMicroExecute {{ + Fault + %(class_name)s::execute( + ExecContext *xc, trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; + } + + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ' ' + << registerName(srcRegIdx(0)) << ' ' << adj; + return ss.str(); + } +}}; + +// Cmpop decode template. +def template CmPopDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst); + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; + + protected: + using %(base_class)s::%(base_class)s; + }; +}}; + + +def template CmPopConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) : + %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + StaticInstPtr cur_inst = nullptr; + if (rlist < 4) { + cur_inst = new Unknown(machInst); + cur_inst->setFlag(IsMicroop); + microops.emplace_back(cur_inst); + } else { + int start_reg = 0; + if (rlist != 15) { + start_reg = (16-rlist); + } + + int offset = stackAdj(); + for (int i = start_reg; i < PushPopRegList.size(); i++) { + offset -= rvSelect(4, 8); + + if (machInst.rv_type == RV32) { + cur_inst = new %(class_name)s32MicroInst( + machInst, PushPopRegList[i], offset); + } else { + cur_inst = new %(class_name)s64MicroInst( + machInst, PushPopRegList[i], offset); + } + microops.emplace_back(cur_inst); + } + + cur_inst = new %(class_name)sSpAdjMicroInst(machInst, stackAdj()); + microops.emplace_back(cur_inst); + + %(move_a0_desc)s; + %(return_desc)s; + } + + microops.front()->setFirstMicroop(); + microops.back()->setLastMicroop(); + } +}}; + +def template CmPopExecute {{ + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << getRlistStr() << ", " << stackAdj(); + return ss.str(); + } +}}; + +def template CmLoadMicroDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegId pop_reg, int64_t offset); + + Fault execute(ExecContext *, trace::InstRecord *) const override; + Fault initiateAcc(ExecContext *, trace::InstRecord *) const override; + Fault completeAcc( + Packet *, ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly( + Addr, const loader::SymbolTable *) const override; + + protected: + using %(base_class)s::%(base_class)s; + + private: + %(reg_idx_arr_decl)s; + + int64_t offset; + Request::Flags memAccessFlags; + }; +}}; + +def template CmLoadMicroConstructor {{ + %(class_name)s::%(class_name)s( + ExtMachInst machInst, RegId pop_reg, int64_t offset) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s), + offset(offset) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template CmLoadMicroExecute {{ + Fault + %(class_name)s::execute( + ExecContext *xc, trace::InstRecord *traceData) const + { + Addr EA; + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + { + Fault fault = + readMemAtomicLE(xc, traceData, EA, Mem, memAccessFlags); + if (fault != NoFault) + return fault; + } + + %(memacc_code)s; + + %(op_wb)s; + + return NoFault; + } + + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", " << + offset << '(' << registerName(srcRegIdx(0)) << ')'; + return ss.str(); + } +}}; + +def template CmLoadMicroInitiateAcc {{ + Fault + %(class_name)s::initiateAcc(ExecContext *xc, + trace::InstRecord *traceData) const + { + Addr EA; + + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + return initiateMemRead(xc, traceData, EA, Mem, memAccessFlags); + } +}}; + +def template CmLoadMicroCompleteAcc {{ + Fault + %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc, + trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + + getMemLE(pkt, Mem, traceData); + + %(memacc_code)s; + %(op_wb)s; + + return NoFault; + } +}}; + +def template CmRetMicroDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + /// Constructor. + %(class_name)s(ExtMachInst machInst); + + protected: + using %(base_class)s::%(base_class)s; + + Fault execute(ExecContext *, trace::InstRecord *) const override; + + std::string + generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; + + std::unique_ptr branchTarget( + ThreadContext *tc) const override; + + using StaticInst::branchTarget; + + private: + %(reg_idx_arr_decl)s; + }; +}}; + +def template CmRetMicroConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template CmRetMicroExecute {{ + Fault + %(class_name)s::execute( + ExecContext *xc, trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; + } + + std::unique_ptr + %(class_name)s::branchTarget(ThreadContext *tc) const + { + PCStateBase *pc_ptr = tc->pcState().clone(); + pc_ptr->as().set(rvSext(tc->getReg(srcRegIdx(0)) & ~0x1)); + return std::unique_ptr{pc_ptr}; + } + + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(srcRegIdx(0)); + return ss.str(); + } +}}; + +// Cmmvsa01 decode template +def template CmMvDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst); + + protected: + using %(base_class)s::%(base_class)s; + + std::string generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const override; + }; +}}; + +def template CmMvsa01Constructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + microops.emplace_back( + new %(class_name)sMvMicroInst( + machInst, int_reg::A0, StackRegs[machInst.r1s])); + microops.emplace_back( + new %(class_name)sMvMicroInst( + machInst, int_reg::A1, StackRegs[machInst.r2s])); + + microops.front()->setFirstMicroop(); + microops.back()->setLastMicroop(); + } +}}; + +def template CmMva01sConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + microops.emplace_back( + new %(class_name)sMvMicroInst( + machInst, StackRegs[machInst.r1s], int_reg::A0)); + microops.emplace_back( + new %(class_name)sMvMicroInst( + machInst, StackRegs[machInst.r2s], int_reg::A1)); + + microops.front()->setFirstMicroop(); + microops.back()->setLastMicroop(); + } +}}; + +def template CmMvExecute {{ + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(StackRegs[machInst.r1s]) + << ", " << registerName(StackRegs[machInst.r2s]); + return ss.str(); + } +}}; + +def template CmMvMicroDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, RegId push_reg, RegId pop_reg); + protected: + using %(base_class)s::%(base_class)s; + + Fault execute(ExecContext *, trace::InstRecord *) const override; + std::string generateDisassembly( + Addr, const loader::SymbolTable *) const override; + + private: + %(reg_idx_arr_decl)s; + }; +}}; + +def template CmMvMicroConstructor {{ + %(class_name)s::%(class_name)s( + ExtMachInst machInst, RegId push_reg, RegId pop_reg) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(set_reg_idx_arr)s; + %(constructor)s; + } +}}; + +def template CmMvMicroExecute {{ + Fault + %(class_name)s::execute( + ExecContext *xc, trace::InstRecord *traceData) const + { + %(op_decl)s; + %(op_rd)s; + %(code)s; + %(op_wb)s; + return NoFault; + } + + std::string + %(class_name)s::generateDisassembly( + Addr pc, const loader::SymbolTable *symtab) const + { + std::stringstream ss; + ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ' ' + << registerName(srcRegIdx(0)); + return ss.str(); + } +}}; + +def format CmPush(*flags) {{ + code = '' + macro_iop = InstObjParams(name, Name, 'CmMacroInst', code, flags) + header_output = CmPushDeclare.subst(macro_iop) + decoder_output = CmPushConstructor.subst(macro_iop) + exec_output = CmPushExecute.subst(macro_iop) + decode_block = BasicDecode.subst(macro_iop) + + memacc_code = 'Mem_sw = CmPushReg_sw;' + ea_code = 'EA = rvSext(sp + offset);' + micro32_iop = InstObjParams('lw', f'{Name}32MicroInst', 'RiscvMicroInst', + {'ea_code': ea_code, 'memacc_code': memacc_code}, + flags) + + mem_flags = [getAlignFlag(micro32_iop)] + s = '\n\tmemAccessFlags = ' + '|'.join(mem_flags) + ';' + micro32_iop.constructor += s + + header_output += CmStoreMicroDeclare.subst(micro32_iop) + decoder_output += CmStoreMicroConstructor.subst(micro32_iop) + exec_output += CmStoreMicroExecute.subst(micro32_iop) \ + + CmStoreMicroInitiateAcc.subst(micro32_iop) \ + + CmStoreMicroCompleteAcc.subst(micro32_iop) + + memacc_code = 'Mem = CmPushReg;' + ea_code = 'EA = rvSext(sp + offset);' + micro64_iop = InstObjParams('ld', f'{Name}64MicroInst', 'RiscvMicroInst', + {'ea_code': ea_code, 'memacc_code': memacc_code}, + flags) + + mem_flags = [getAlignFlag(micro64_iop)] + s = '\n\tmemAccessFlags = ' + '|'.join(mem_flags) + ';' + micro64_iop.constructor += s + + header_output += CmStoreMicroDeclare.subst(micro64_iop) + decoder_output += CmStoreMicroConstructor.subst(micro64_iop) + exec_output += CmStoreMicroExecute.subst(micro64_iop) \ + + CmStoreMicroInitiateAcc.subst(micro64_iop) \ + + CmStoreMicroCompleteAcc.subst(micro64_iop) + + code = 'spd = rvSext(sp + adj);' + sp_adj_iop = InstObjParams('addi', f'{Name}SpAdjMicroInst', + 'RiscvMicroInst', code, flags) + + header_output += SpAdjMicroDeclare.subst(sp_adj_iop) + decoder_output += SpAdjMicroConstructor.subst(sp_adj_iop) + exec_output += SpAdjMicroExecute.subst(sp_adj_iop) +}}; + +def format CmPop(is_ret=False, has_a0=False, *flags) {{ + code = '' + flags = [] + has_a0 = eval(has_a0) + is_ret = eval(is_ret) + move_a0_desc = '' + return_desc = '' + + if has_a0: + move_a0_desc = rf''' + cur_inst = new {Name}MvMicroInst( + machInst, ReturnValueReg, int_reg::Zero); + microops.emplace_back(cur_inst); + ''' + + if is_ret: + return_desc = rf''' + cur_inst = new {Name}RetMicroInst(machInst); + microops.emplace_back(cur_inst); + ''' + + macro_iop = InstObjParams(name, Name, 'CmMacroInst', + {'code': code, 'move_a0_desc': move_a0_desc, + 'return_desc': return_desc}, + flags) + header_output = CmPopDeclare.subst(macro_iop) + decoder_output = CmPopConstructor.subst(macro_iop) + exec_output = CmPopExecute.subst(macro_iop) + decode_block = BasicDecode.subst(macro_iop) + + memacc_code = 'CmPopReg_sw = Mem_sw;' + ea_code = 'EA = rvSext(sp + offset);' + micro32_iop = InstObjParams('lw', f'{Name}32MicroInst', 'RiscvMicroInst', + {'ea_code': ea_code, 'memacc_code': memacc_code}, + flags) + + mem_flags = [getAlignFlag(micro32_iop)] + s = '\n\tmemAccessFlags = ' + '|'.join(mem_flags) + ';' + micro32_iop.constructor += s + + header_output += CmLoadMicroDeclare.subst(micro32_iop) + decoder_output += CmLoadMicroConstructor.subst(micro32_iop) + exec_output += CmLoadMicroExecute.subst(micro32_iop) \ + + CmLoadMicroInitiateAcc.subst(micro32_iop) \ + + CmLoadMicroCompleteAcc.subst(micro32_iop) + + memacc_code = 'CmPopReg = Mem;' + ea_code = 'EA = rvSext(sp + offset);' + micro64_iop = InstObjParams('ld', f'{Name}64MicroInst', 'RiscvMicroInst', + {'ea_code': ea_code, 'memacc_code': memacc_code}, + flags) + + mem_flags = [getAlignFlag(micro64_iop)] + s = '\n\tmemAccessFlags = ' + '|'.join(mem_flags) + ';' + micro64_iop.constructor += s + + header_output += CmLoadMicroDeclare.subst(micro64_iop) + decoder_output += CmLoadMicroConstructor.subst(micro64_iop) + exec_output += CmLoadMicroExecute.subst(micro64_iop) \ + + CmLoadMicroInitiateAcc.subst(micro64_iop) \ + + CmLoadMicroCompleteAcc.subst(micro64_iop) + + code = 'spd = rvSext(sp + adj);' + sp_adj_iop = InstObjParams('addi', f'{Name}SpAdjMicroInst', + 'RiscvMicroInst', code, flags) + + header_output += SpAdjMicroDeclare.subst(sp_adj_iop) + decoder_output += SpAdjMicroConstructor.subst(sp_adj_iop) + exec_output += SpAdjMicroExecute.subst(sp_adj_iop) + + if has_a0: + code = 'CmPopReg = CmPushReg;' + has_a0_iop = InstObjParams('mv', f'{Name}MvMicroInst', + 'RiscvMicroInst', code, flags) + + header_output += CmMvMicroDeclare.subst(has_a0_iop) + decoder_output += CmMvMicroConstructor.subst(has_a0_iop) + exec_output += CmMvMicroExecute.subst(has_a0_iop) + + if is_ret: + code = 'NPC = rvSext(ra & (~0x1));' + ret_flags = ['IsIndirectControl', 'IsUncondControl', 'IsReturn'] + is_ret_iop = InstObjParams('jr', f'{Name}RetMicroInst', + 'RiscvMicroInst', code, ret_flags) + + header_output += CmRetMicroDeclare.subst(is_ret_iop) + decoder_output += CmRetMicroConstructor.subst(is_ret_iop) + exec_output += CmRetMicroExecute.subst(is_ret_iop) +}}; + +def format CmMvsa01() {{ + code = '' + flags = [] + iop = InstObjParams(name, Name, 'RiscvMacroInst', code, flags) + header_output = CmMvDeclare.subst(iop) + decoder_output = CmMvsa01Constructor.subst(iop) + exec_output = CmMvExecute.subst(iop) + decode_block = BasicDecode.subst(iop) + + code = 'CmPopReg = CmPushReg;' + micro_iop = InstObjParams('mv', f'{Name}MvMicroInst', 'RiscvMicroInst', + code, flags) + + header_output += CmMvMicroDeclare.subst(micro_iop) + decoder_output += CmMvMicroConstructor.subst(micro_iop) + exec_output += CmMvMicroExecute.subst(micro_iop) +}}; + +def format CmMva01s() {{ + code = '' + flags = [] + iop = InstObjParams(name, Name, 'RiscvMacroInst', code, flags) + header_output = CmMvDeclare.subst(iop) + decoder_output = CmMva01sConstructor.subst(iop) + exec_output = CmMvExecute.subst(iop) + decode_block = BasicDecode.subst(iop) + + code = 'CmPopReg = CmPushReg;' + micro_iop = InstObjParams('mv', f'{Name}MvMicroInst', 'RiscvMicroInst', + code, flags) + + header_output += CmMvMicroDeclare.subst(micro_iop) + decoder_output += CmMvMicroConstructor.subst(micro_iop) + exec_output += CmMvMicroExecute.subst(micro_iop) +}}; diff --git a/src/arch/riscv/isa/includes.isa b/src/arch/riscv/isa/includes.isa index b37e62bca8..4d53958723 100644 --- a/src/arch/riscv/isa/includes.isa +++ b/src/arch/riscv/isa/includes.isa @@ -55,6 +55,7 @@ output header {{ #include "arch/riscv/insts/static_inst.hh" #include "arch/riscv/insts/unknown.hh" #include "arch/riscv/insts/vector.hh" +#include "arch/riscv/insts/zcmp.hh" #include "arch/riscv/interrupts.hh" #include "cpu/static_inst.hh" #include "mem/packet.hh" diff --git a/src/arch/riscv/isa/operands.isa b/src/arch/riscv/isa/operands.isa index de36d902b1..e2a7522b94 100644 --- a/src/arch/riscv/isa/operands.isa +++ b/src/arch/riscv/isa/operands.isa @@ -70,10 +70,14 @@ def operands {{ 'Rp2': IntReg('ud', 'RP2 + 8', 'IsInteger', 3), 'ra': IntReg('ud', 'ReturnAddrReg', 'IsInteger', 1), 'sp': IntReg('ud', 'StackPointerReg', 'IsInteger', 2), + 'spd': IntReg('ud', 'StackPointerReg', 'IsInteger', 1), 'a0': IntReg('ud', '10', 'IsInteger', 1), 'a1': IntReg('ud', '11', 'IsInteger', 2), + 'CmPushReg': IntReg('ud', 'push_reg', 'IsInteger', 3), + 'CmPopReg': IntReg('ud', 'pop_reg', 'IsInteger', 1), + 'Fd': FloatRegOp('df', 'FD', 'IsFloating', 1), 'Fd_bits': FloatRegOp('ud', 'FD', 'IsFloating', 1), 'Fs1': FloatRegOp('df', 'FS1', 'IsFloating', 2), diff --git a/src/arch/riscv/regs/int.hh b/src/arch/riscv/regs/int.hh index 4ac01c60c1..dc7e37cdbe 100644 --- a/src/arch/riscv/regs/int.hh +++ b/src/arch/riscv/regs/int.hh @@ -149,6 +149,18 @@ inline constexpr RegId ArgumentRegs[] = { int_reg::A4, int_reg::A5, int_reg::A6, int_reg::A7 }; +const std::vector PushPopRegList = { + int_reg::S11, int_reg::S10, int_reg::S9, int_reg::S8, + int_reg::S7, int_reg::S6, int_reg::S5, int_reg::S4, + int_reg::S3, int_reg::S2, int_reg::S1, int_reg::S0, + int_reg::Ra +}; + +inline constexpr RegId StackRegs[] = { + int_reg::S0, int_reg::S1, int_reg::S2, int_reg::S3, + int_reg::S4, int_reg::S5, int_reg::S6, int_reg::S7, +}; + } // namespace RiscvISA } // namespace gem5 diff --git a/src/arch/riscv/types.hh b/src/arch/riscv/types.hh index 4bd3168804..8b72c782a9 100644 --- a/src/arch/riscv/types.hh +++ b/src/arch/riscv/types.hh @@ -127,6 +127,8 @@ BitUnion64(ExtMachInst) Bitfield< 6, 2> rc2; Bitfield< 9, 7> rp1; Bitfield< 4, 2> rp2; + Bitfield< 9, 7> r1s; + Bitfield< 4, 2> r2s; Bitfield<11, 7> fc1; Bitfield< 6, 2> fc2; Bitfield< 4, 2> fp2; @@ -145,6 +147,8 @@ BitUnion64(ExtMachInst) Bitfield<12, 10> cimm3; Bitfield< 6, 5> cimm2; Bitfield<12> cimm1; + Bitfield< 7, 4> rlist; + Bitfield< 3, 2> spimm; // Pseudo instructions Bitfield<31, 25> m5func; // vector