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:
@@ -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')
|
||||
|
||||
130
src/arch/riscv/insts/zcmp.cc
Normal file
130
src/arch/riscv/insts/zcmp.cc
Normal 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
|
||||
60
src/arch/riscv/insts/zcmp.hh
Normal file
60
src/arch/riscv/insts/zcmp.hh
Normal 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__
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
772
src/arch/riscv/isa/formats/zcmp.isa
Normal file
772
src/arch/riscv/isa/formats/zcmp.isa
Normal 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)
|
||||
}};
|
||||
@@ -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"
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user