arch-riscv: Implement Zcmp instructions (#1432)
1. Implement Zcmp(cm.push, cm.pop, cm.popret, cm.popretz, cm.mva01s, cm.mvsa01) instructions 2. The Zcd instructions overlap the Zcmp and Zcmt instruction. This option is used to enable/disable Zcd extension, implies enable Zcmp/Zcmt extension. If Zcd is enable, the Zcmp and Zcmt is disabled. Otherwise, Zcmp and Zcmt is enabled. Spec: https://github.com/riscv/riscv-isa-manual/blob/main/src/zc.adoc
This commit is contained in:
@@ -114,6 +114,13 @@ class RiscvISA(BaseISA):
|
||||
|
||||
enable_Zicbom_fs = Param.Bool(True, "Enable Zicbom extension in FS mode")
|
||||
enable_Zicboz_fs = Param.Bool(True, "Enable Zicboz extension in FS mode")
|
||||
enable_Zcd = Param.Bool(
|
||||
True,
|
||||
"Enable Zcd extensions. "
|
||||
"Set the option to false implies the Zcmp and Zcmt is enable as "
|
||||
"c.fsdsp is overlap with them."
|
||||
"Refs: https://github.com/riscv/riscv-isa-manual/blob/main/src/zc.adoc",
|
||||
)
|
||||
|
||||
wfi_resume_on_pending = Param.Bool(
|
||||
False,
|
||||
|
||||
@@ -44,6 +44,7 @@ Decoder::Decoder(const RiscvDecoderParams &p) : InstDecoder(p, &machInst)
|
||||
ISA *isa = dynamic_cast<ISA*>(p.isa);
|
||||
vlen = isa->getVecLenInBits();
|
||||
elen = isa->getVecElemLenInBits();
|
||||
_enableZcd = isa->enableZcd();
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -127,6 +128,7 @@ Decoder::decode(PCStateBase &_next_pc)
|
||||
emi.vtype8 = next_pc.vtype() & 0xff;
|
||||
emi.vill = next_pc.vtype().vill;
|
||||
emi.rv_type = static_cast<int>(next_pc.rvType());
|
||||
emi.enable_zcd = _enableZcd;
|
||||
|
||||
return decode(emi, next_pc.instAddr());
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ class Decoder : public InstDecoder
|
||||
|
||||
uint32_t vlen;
|
||||
uint32_t elen;
|
||||
bool _enableZcd;
|
||||
|
||||
virtual StaticInstPtr decodeInst(ExtMachInst mach_inst);
|
||||
|
||||
|
||||
@@ -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__
|
||||
@@ -260,7 +260,7 @@ RegClass ccRegClass(CCRegClass, CCRegClassName, 0, debug::IntRegs);
|
||||
ISA::ISA(const Params &p) : BaseISA(p, "riscv"),
|
||||
_rvType(p.riscv_type), enableRvv(p.enable_rvv), vlen(p.vlen), elen(p.elen),
|
||||
_privilegeModeSet(p.privilege_mode_set),
|
||||
_wfiResumeOnPending(p.wfi_resume_on_pending)
|
||||
_wfiResumeOnPending(p.wfi_resume_on_pending), _enableZcd(p.enable_Zcd)
|
||||
{
|
||||
_regClasses.push_back(&intRegClass);
|
||||
_regClasses.push_back(&floatRegClass);
|
||||
|
||||
@@ -108,6 +108,14 @@ class ISA : public BaseISA
|
||||
*/
|
||||
const bool _wfiResumeOnPending;
|
||||
|
||||
/**
|
||||
* Enable Zcd extensions.
|
||||
* Set the option to false implies the Zcmp and Zcmt is enable as c.fsdsp
|
||||
* is overlap with them.
|
||||
* Refs: https://github.com/riscv/riscv-isa-manual/blob/main/src/zc.adoc
|
||||
*/
|
||||
bool _enableZcd;
|
||||
|
||||
public:
|
||||
using Params = RiscvISAParams;
|
||||
|
||||
@@ -184,6 +192,8 @@ class ISA : public BaseISA
|
||||
|
||||
bool resumeOnPending() { return _wfiResumeOnPending; }
|
||||
|
||||
bool enableZcd() { return _enableZcd; }
|
||||
|
||||
virtual Addr getFaultHandlerAddr(
|
||||
RegIndex idx, uint64_t cause, bool intr) const;
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
// Bitfield definitions.
|
||||
//
|
||||
def bitfield RVTYPE rv_type;
|
||||
def bitfield ENABLE_ZCD enable_zcd;
|
||||
|
||||
def bitfield QUADRANT <1:0>;
|
||||
def bitfield OPCODE5 <6:2>;
|
||||
@@ -103,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>;
|
||||
|
||||
@@ -54,23 +54,25 @@ decode QUADRANT default Unknown::unknown() {
|
||||
Rp2 = rvSext(sp + imm);
|
||||
}}, uint64_t);
|
||||
format CompressedLoad {
|
||||
0x1: c_fld({{
|
||||
offset = CIMM3 << 3 | CIMM2 << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
0x1: decode ENABLE_ZCD {
|
||||
0x1: c_fld({{
|
||||
offset = CIMM3 << 3 | CIMM2 << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
|
||||
// Mutating any floating point register changes the FS bit
|
||||
// of the STATUS CSR.
|
||||
status.fs = FPUStatus::DIRTY;
|
||||
xc->setMiscReg(MISCREG_STATUS, status);
|
||||
// Mutating any floating point register changes the FS bit
|
||||
// of the STATUS CSR.
|
||||
status.fs = FPUStatus::DIRTY;
|
||||
xc->setMiscReg(MISCREG_STATUS, status);
|
||||
|
||||
Fp2_bits = Mem;
|
||||
}}, {{
|
||||
EA = rvSext(Rp1 + offset);
|
||||
}});
|
||||
Fp2_bits = Mem;
|
||||
}}, {{
|
||||
EA = rvSext(Rp1 + offset);
|
||||
}});
|
||||
}
|
||||
0x2: c_lw({{
|
||||
offset = CIMM2<1:1> << 2 |
|
||||
CIMM3 << 3 |
|
||||
@@ -152,18 +154,20 @@ decode QUADRANT default Unknown::unknown() {
|
||||
}
|
||||
}
|
||||
format CompressedStore {
|
||||
0x5: c_fsd({{
|
||||
offset = CIMM3 << 3 | CIMM2 << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
0x5: decode ENABLE_ZCD {
|
||||
0x1: c_fsd({{
|
||||
offset = CIMM3 << 3 | CIMM2 << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
|
||||
Mem = Fp2_bits;
|
||||
}}, {{
|
||||
EA = rvSext(Rp1 + offset);
|
||||
}});
|
||||
Mem = Fp2_bits;
|
||||
}}, {{
|
||||
EA = rvSext(Rp1 + offset);
|
||||
}});
|
||||
}
|
||||
0x6: c_sw({{
|
||||
offset = CIMM2<1:1> << 2 |
|
||||
CIMM3 << 3 |
|
||||
@@ -381,23 +385,25 @@ decode QUADRANT default Unknown::unknown() {
|
||||
Rc1 = rvSext(Rc1 << imm);
|
||||
}}, uint64_t);
|
||||
format CompressedLoad {
|
||||
0x1: c_fldsp({{
|
||||
offset = CIMM5<4:3> << 3 |
|
||||
CIMM1 << 5 |
|
||||
CIMM5<2:0> << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
0x1: decode ENABLE_ZCD {
|
||||
0x1: c_fldsp({{
|
||||
offset = CIMM5<4:3> << 3 |
|
||||
CIMM1 << 5 |
|
||||
CIMM5<2:0> << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
|
||||
status.fs = FPUStatus::DIRTY;
|
||||
xc->setMiscReg(MISCREG_STATUS, status);
|
||||
status.fs = FPUStatus::DIRTY;
|
||||
xc->setMiscReg(MISCREG_STATUS, status);
|
||||
|
||||
Fc1_bits = Mem;
|
||||
}}, {{
|
||||
EA = rvSext(sp + offset);
|
||||
}});
|
||||
Fc1_bits = Mem;
|
||||
}}, {{
|
||||
EA = rvSext(sp + offset);
|
||||
}});
|
||||
}
|
||||
0x2: c_lwsp({{
|
||||
offset = CIMM5<4:2> << 2 |
|
||||
CIMM1 << 5 |
|
||||
@@ -480,19 +486,35 @@ decode QUADRANT default Unknown::unknown() {
|
||||
}
|
||||
}
|
||||
format CompressedStore {
|
||||
0x5: c_fsdsp({{
|
||||
offset = CIMM6<5:3> << 3 |
|
||||
CIMM6<2:0> << 6;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
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;
|
||||
}}, {{
|
||||
STATUS status = xc->readMiscReg(MISCREG_STATUS);
|
||||
if (status.fs == FPUStatus::OFF)
|
||||
return std::make_shared<IllegalInstFault>("FPU is off",
|
||||
machInst);
|
||||
|
||||
Mem_ud = Fc2_bits;
|
||||
}}, {{
|
||||
EA = rvSext(sp + offset);
|
||||
}});
|
||||
Mem_ud = Fc2_bits;
|
||||
}}, {{
|
||||
EA = rvSext(sp + offset);
|
||||
}});
|
||||
}
|
||||
0x6: c_swsp({{
|
||||
offset = CIMM6<5:2> << 2 |
|
||||
CIMM6<1: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"
|
||||
|
||||
782
src/arch/riscv/isa/formats/zcmp.isa
Normal file
782
src/arch/riscv/isa/formats/zcmp.isa
Normal file
@@ -0,0 +1,782 @@
|
||||
// -*- 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);
|
||||
cur_inst->setDelayedCommit();
|
||||
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);
|
||||
}
|
||||
cur_inst->setDelayedCommit();
|
||||
microops.emplace_back(cur_inst);
|
||||
}
|
||||
|
||||
cur_inst = new %(class_name)sSpAdjMicroInst(machInst, -stackAdj());
|
||||
cur_inst->setDelayedCommit();
|
||||
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);
|
||||
cur_inst->setDelayedCommit();
|
||||
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);
|
||||
}
|
||||
cur_inst->setDelayedCommit();
|
||||
microops.emplace_back(cur_inst);
|
||||
}
|
||||
|
||||
cur_inst = new %(class_name)sSpAdjMicroInst(machInst, stackAdj());
|
||||
cur_inst->setDelayedCommit();
|
||||
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)
|
||||
{
|
||||
StaticInstPtr cur_inst;
|
||||
cur_inst = new %(class_name)sMvMicroInst(
|
||||
machInst, int_reg::A0, StackRegs[machInst.r1s]);
|
||||
microops.emplace_back(cur_inst);
|
||||
cur_inst = new %(class_name)sMvMicroInst(
|
||||
machInst, int_reg::A1, StackRegs[machInst.r2s]);
|
||||
microops.emplace_back(cur_inst);
|
||||
|
||||
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)
|
||||
{
|
||||
StaticInstPtr cur_inst;
|
||||
cur_inst = new %(class_name)sMvMicroInst(
|
||||
machInst, StackRegs[machInst.r1s], int_reg::A0);
|
||||
cur_inst->setDelayedCommit();
|
||||
microops.emplace_back(cur_inst);
|
||||
cur_inst = new %(class_name)sMvMicroInst(
|
||||
machInst, StackRegs[machInst.r2s], int_reg::A1);
|
||||
cur_inst->setDelayedCommit();
|
||||
microops.emplace_back(cur_inst);
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ BitUnion64(ExtMachInst)
|
||||
// Decoder state
|
||||
Bitfield<63, 62> rv_type;
|
||||
Bitfield<61> compressed;
|
||||
Bitfield<60> enable_zcd;
|
||||
// More bits for vector extension
|
||||
Bitfield<57, 41> vl; // [0, 2**16]
|
||||
Bitfield<40> vill;
|
||||
@@ -126,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;
|
||||
@@ -144,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