arch-arm: Implement FEAT_FLAGM(2)

Change-Id: I21f1eb91ad9acb019a776a7d5edd38754571a62e
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Richard Cooper <richard.cooper@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/70719
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Giacomo Travaglini
2023-03-06 19:37:39 +00:00
parent 223a07031f
commit e3d2191b73
9 changed files with 244 additions and 4 deletions

View File

@@ -58,6 +58,10 @@ class ArmDefaultSERelease(ArmRelease):
"FEAT_FCMA",
"FEAT_JSCVT",
"FEAT_PAuth",
# Armv8.4
"FEAT_FLAGM",
# Armv8.5
"FEAT_FLAGM2",
# Armv9.2
"FEAT_SME",
# Other

View File

@@ -85,6 +85,9 @@ class ArmExtension(ScopedEnum):
# Armv8.4
"FEAT_SEL2",
"FEAT_TLBIOS",
"FEAT_FLAGM",
# Armv8.5
"FEAT_FLAGM2",
# Armv9.2
"FEAT_SME", # Optional in Armv9.2
# Others
@@ -164,6 +167,9 @@ class ArmDefaultRelease(Armv8):
# Armv8.4
"FEAT_SEL2",
"FEAT_TLBIOS",
"FEAT_FLAGM",
# Armv8.5
"FEAT_FLAGM2",
# Armv9.2
"FEAT_SME",
]
@@ -194,11 +200,15 @@ class Armv83(Armv82):
class Armv84(Armv83):
extensions = Armv83.extensions + ["FEAT_SEL2", "FEAT_TLBIOS"]
extensions = Armv83.extensions + ["FEAT_SEL2", "FEAT_TLBIOS", "FEAT_FLAGM"]
class Armv92(Armv84):
extensions = Armv84.extensions + ["FEAT_SME"]
class Armv85(Armv84):
extensions = Armv84.extensions + ["FEAT_FLAGM2"]
class Armv92(Armv85):
extensions = Armv85.extensions + ["FEAT_SME"]
class ArmSystem(System):

View File

@@ -54,6 +54,27 @@ ImmOp64::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const
return ss.str();
}
std::string
RegOp64::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, "", false);
printIntReg(ss, op1);
return ss.str();
}
std::string
RegImmImmOp64::generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss, "", false);
printIntReg(ss, op1);
ccprintf(ss, "#0x%x", imm1);
ss << ", ";
ccprintf(ss, "#0x%x", imm2);
return ss.str();
}
std::string
RegRegImmImmOp64::generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const

View File

@@ -57,6 +57,38 @@ class ImmOp64 : public ArmISA::ArmStaticInst
Addr pc, const loader::SymbolTable *symtab) const override;
};
class RegOp64 : public ArmISA::ArmStaticInst
{
protected:
RegIndex op1;
RegOp64(const char *mnem, ArmISA::ExtMachInst _machInst,
OpClass __opClass, RegIndex _op1) :
ArmISA::ArmStaticInst(mnem, _machInst, __opClass), op1(_op1)
{}
std::string generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const override;
};
class RegImmImmOp64 : public ArmISA::ArmStaticInst
{
protected:
RegIndex op1;
uint64_t imm1;
uint64_t imm2;
RegImmImmOp64(const char *mnem, ArmISA::ExtMachInst _machInst,
OpClass __opClass, RegIndex _op1,
uint64_t _imm1, uint64_t _imm2) :
ArmISA::ArmStaticInst(mnem, _machInst, __opClass),
op1(_op1), imm1(_imm1), imm2(_imm2)
{}
std::string generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const override;
};
class RegRegImmImmOp64 : public ArmISA::ArmStaticInst
{
protected:

View File

@@ -424,6 +424,15 @@ namespace Aarch64
// MSR immediate: moving immediate value to selected
// bits of the PSTATE
switch (op1 << 3 | op2) {
case 0x0:
// CFINV
return new Cfinv(machInst);
case 0x1:
// XAFLAG
return new Xaflag(machInst);
case 0x2:
// AXFLAG
return new Axflag(machInst);
case 0x3:
// UAO
return new MsrImm64(
@@ -2080,6 +2089,26 @@ namespace Aarch64
}
}
StaticInstPtr
decodeRotIntoFlags(ExtMachInst machInst)
{
RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5);
uint8_t imm6 = bits(machInst, 20, 15);
uint8_t mask = bits(machInst, 3, 0);
return new Rmif(machInst, rn, imm6, mask);
}
StaticInstPtr
decodeEvalIntoFlags(ExtMachInst machInst)
{
RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5);
int sz = bits(machInst, 14);
if (sz)
return new Setf16(machInst, rn);
else
return new Setf8(machInst, rn);
}
StaticInstPtr
decodeCondCompare(ExtMachInst machInst)
{
@@ -2328,7 +2357,16 @@ namespace Aarch64
switch (bits(machInst, 23, 22)) {
case 0x0:
return decodeAddSubWithCarry(machInst);
switch (bits(machInst, 11, 10)) {
case 0b00:
return decodeAddSubWithCarry(machInst);
case 0b01:
return decodeRotIntoFlags(machInst);
case 0b10:
return decodeEvalIntoFlags(machInst);
default: // 0b11
return new Unknown64(machInst);
}
case 0x1:
return decodeCondCompare(machInst);
case 0x2:

View File

@@ -248,4 +248,81 @@ let {{
header_output += ImmOp64Declare.subst(hltIop)
decoder_output += SemihostConstructor64.subst(hltIop)
exec_output += BasicExecute.subst(hltIop)
flagmCheckCode = '''
if (!HaveExt(xc->tcBase(), ArmExtension::FEAT_FLAGM)) {
return std::make_shared<UndefinedInstruction>(
machInst, true);
}
'''
cfinvCode = 'CondCodesC = ~CondCodesC'
cfinvIop = ArmInstObjParams("cfinv", "Cfinv", "ArmStaticInst",
flagmCheckCode + cfinvCode)
header_output += BasicDeclare.subst(cfinvIop)
decoder_output += BasicConstructor64.subst(cfinvIop)
exec_output += BasicExecute.subst(cfinvIop)
axflagCode = '''
bool z = CondCodesNZ || CondCodesV;
bool c = CondCodesC && !CondCodesV;
CondCodesNZ = z; // This implies zeroing PSTATE.N
CondCodesC = c;
CondCodesV = 0;
'''
axflagIop = ArmInstObjParams("axflag", "Axflag", "ArmStaticInst",
flagmCheckCode + axflagCode)
header_output += BasicDeclare.subst(axflagIop)
decoder_output += BasicConstructor64.subst(axflagIop)
exec_output += BasicExecute.subst(axflagIop)
xaflagCode = '''
const RegVal nz = CondCodesNZ;
const RegVal n = !CondCodesC && !bits(nz, 0);
const RegVal z = CondCodesC && bits(nz, 0);
const RegVal c = CondCodesC || bits(nz, 0);
const RegVal v = !CondCodesC && bits(nz, 0);
CondCodesNZ = (n << 1) | z;
CondCodesC = c;
CondCodesV = v;
'''
xaflagIop = ArmInstObjParams("xaflag", "Xaflag", "ArmStaticInst",
flagmCheckCode + xaflagCode)
header_output += BasicDeclare.subst(xaflagIop)
decoder_output += BasicConstructor64.subst(xaflagIop)
exec_output += BasicExecute.subst(xaflagIop)
rmifCode = '''
RegVal tmp = XOp1 << imm1;
int nz = CondCodesNZ;
if (bits(imm2, 0)) CondCodesV = bits(tmp, 0);
if (bits(imm2, 1)) CondCodesC = bits(tmp, 1);
if (bits(imm2, 2)) nz = insertBits(nz, 0, bits(tmp, 2));
if (bits(imm2, 3)) nz = insertBits(nz, 1, bits(tmp, 3));
CondCodesNZ = nz;
'''
rmifIop = ArmInstObjParams("rmif", "Rmif", "RegImmImmOp64",
flagmCheckCode + rmifCode)
header_output += RegImmImmOp64Declare.subst(rmifIop)
decoder_output += RegImmImmOp64Constructor.subst(rmifIop)
exec_output += BasicExecute.subst(rmifIop)
setfCode = '''
const int msb = %d;
RegVal tmp = Op1;
CondCodesNZ = (bits(tmp, msb) << 1) | (bits(tmp, msb, 0) ? 0 : 1);
CondCodesV = bits(tmp, msb) ^ bits(tmp, msb + 1);
'''
setf8Iop = ArmInstObjParams("setf8", "Setf8", "RegOp64",
flagmCheckCode + setfCode % 7)
header_output += RegOp64Declare.subst(setf8Iop)
decoder_output += RegOp64Constructor.subst(setf8Iop)
exec_output += BasicExecute.subst(setf8Iop)
setf16Iop = ArmInstObjParams("setf16", "Setf16", "RegOp64",
flagmCheckCode + setfCode % 15)
header_output += RegOp64Declare.subst(setf16Iop)
decoder_output += RegOp64Constructor.subst(setf16Iop)
exec_output += BasicExecute.subst(setf16Iop)
}};

View File

@@ -58,6 +58,56 @@ def template ImmOp64Constructor {{
}
}};
def template RegOp64Declare {{
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
// Constructor
%(class_name)s(ExtMachInst machInst, RegIndex _op1);
Fault execute(ExecContext *, trace::InstRecord *) const override;
};
}};
def template RegOp64Constructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst, RegIndex _op1) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _op1)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
}};
def template RegImmImmOp64Declare {{
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
RegIndex _op1,
uint64_t _imm1, uint64_t _imm2);
Fault execute(ExecContext *, trace::InstRecord *) const override;
};
}};
def template RegImmImmOp64Constructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
RegIndex _op1,
uint64_t _imm1, uint64_t _imm2) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_op1, _imm1, _imm2)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
}};
def template RegRegImmImmOp64Declare {{
class %(class_name)s : public %(base_class)s
{

View File

@@ -314,6 +314,11 @@ ArmProcess64::armHwcapImpl2() const
uint64_t hwcap = 0;
ThreadContext *tc = system->threads[contextIds[0]];
const AA64ISAR0 isa_r0 = tc->readMiscReg(MISCREG_ID_AA64ISAR0_EL1);
hwcap |= (isa_r0.ts >= 2) ? Arm_Flagm2 : Arm_None;
return hwcap;
}

View File

@@ -3891,6 +3891,9 @@ ISA::initializeMiscRegMetadata()
isar0_el1.rdm = release->has(ArmExtension::FEAT_RDM) ? 0x1 : 0x0;
isar0_el1.tme = release->has(ArmExtension::TME) ? 0x1 : 0x0;
isar0_el1.tlb = release->has(ArmExtension::FEAT_TLBIOS) ? 0x1 : 0x0;
isar0_el1.ts = release->has(ArmExtension::FEAT_FLAGM2) ?
0x2 : release->has(ArmExtension::FEAT_FLAGM) ?
0x1 : 0x0;
return isar0_el1;
}())
.faultRead(EL1, HCR_TRAP(tid3))