arch-riscv: Implement Zcmp

Implement instructions:
cm.push
cm.pop
cm.popret
cm.popretz
cm.mva01s
cm.mvsa01

Spec: https://github.com/riscv/riscv-isa-manual/blob/main/src/zc.adoc#zcmp

Change-Id: I2921c4bdb0c654858a237386056ebb2aed643a5a
This commit is contained in:
Roger Chang
2024-07-04 16:02:49 +08:00
parent aa782cffee
commit 28b112e2a6
11 changed files with 1002 additions and 0 deletions

View File

@@ -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')

View File

@@ -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 <string>
#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

View File

@@ -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 <string>
#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__

View File

@@ -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>;

View File

@@ -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;

View File

@@ -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"

View File

@@ -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<PCStateBase> 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<PCStateBase>
%(class_name)s::branchTarget(ThreadContext *tc) const
{
PCStateBase *pc_ptr = tc->pcState().clone();
pc_ptr->as<PCState>().set(rvSext(tc->getReg(srcRegIdx(0)) & ~0x1));
return std::unique_ptr<PCStateBase>{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)
}};

View File

@@ -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"

View File

@@ -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),

View File

@@ -149,6 +149,18 @@ inline constexpr RegId ArgumentRegs[] = {
int_reg::A4, int_reg::A5, int_reg::A6, int_reg::A7
};
const std::vector<RegId> 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

View File

@@ -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