arch-power: Add trap instructions
This introduces new classes and new formats for D and X form instructions, the TO field that is used to encode the trap conditions and adds the following instructions. * Trap Word Immediate (twi) * Trap Word (tw) * Trap Doubleword Immediate (tdi) * Trap Doubleword (td) Change-Id: I029147ef643c2ee6794426e5e90af4d75f22e92e Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40934 Reviewed-by: Boris Shingarov <shingarov@labware.com> Maintainer: Boris Shingarov <shingarov@labware.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Boris Shingarov
parent
84837422d8
commit
57181ee613
@@ -82,6 +82,16 @@ class AlignmentFault : public PowerFault
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TrapFault : public PowerFault
|
||||
{
|
||||
public:
|
||||
TrapFault()
|
||||
: PowerFault("Trap")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace PowerISA
|
||||
|
||||
#endif // __ARCH_POWER_FAULTS_HH__
|
||||
|
||||
@@ -820,3 +820,99 @@ IntConcatRotateOp::generateDisassembly(
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
IntTrapOp::generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::string ext;
|
||||
std::stringstream ss;
|
||||
bool printSrcs = true;
|
||||
bool printCond = false;
|
||||
|
||||
// Generate the correct mnemonic
|
||||
std::string myMnemonic(mnemonic);
|
||||
|
||||
// Special cases
|
||||
if (myMnemonic == "tw" &&
|
||||
(srcRegIdx(0).index() == 0) && (srcRegIdx(1).index() == 0)) {
|
||||
myMnemonic = "trap";
|
||||
printSrcs = false;
|
||||
} else {
|
||||
ext = suffix();
|
||||
if (!ext.empty() &&
|
||||
(myMnemonic == "tw" || myMnemonic == "td")) {
|
||||
myMnemonic += ext;
|
||||
} else {
|
||||
printCond = true;
|
||||
}
|
||||
}
|
||||
|
||||
ccprintf(ss, "%-10s ", myMnemonic);
|
||||
|
||||
// Print the trap condition
|
||||
if (printCond)
|
||||
ss << (int) to;
|
||||
|
||||
// Print the source registers
|
||||
if (printSrcs) {
|
||||
if (_numSrcRegs > 0) {
|
||||
if (printCond)
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(0));
|
||||
}
|
||||
|
||||
if (_numSrcRegs > 1) {
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(1));
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
IntImmTrapOp::generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::string ext;
|
||||
std::stringstream ss;
|
||||
bool printCond = false;
|
||||
|
||||
// Generate the correct mnemonic
|
||||
std::string myMnemonic(mnemonic);
|
||||
|
||||
// Special cases
|
||||
ext = suffix();
|
||||
if (!ext.empty()) {
|
||||
if (myMnemonic == "twi") {
|
||||
myMnemonic = "tw" + ext + "i";
|
||||
} else if (myMnemonic == "tdi") {
|
||||
myMnemonic = "td" + ext + "i";
|
||||
} else {
|
||||
printCond = true;
|
||||
}
|
||||
} else {
|
||||
printCond = true;
|
||||
}
|
||||
|
||||
ccprintf(ss, "%-10s ", myMnemonic);
|
||||
|
||||
// Print the trap condition
|
||||
if (printCond)
|
||||
ss << (int) to;
|
||||
|
||||
// Print the source registers
|
||||
if (_numSrcRegs > 0) {
|
||||
if (printCond)
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(0));
|
||||
}
|
||||
|
||||
// Print the immediate value
|
||||
ss << ", " << si;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -713,6 +713,82 @@ class IntConcatRotateOp : public IntConcatShiftOp
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for integer trap operations.
|
||||
*/
|
||||
class IntTrapOp : public IntOp
|
||||
{
|
||||
protected:
|
||||
uint8_t to;
|
||||
|
||||
/// Constructor
|
||||
IntTrapOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: IntOp(mnem, _machInst, __opClass),
|
||||
to(machInst.to)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool
|
||||
checkTrap(int64_t a, int64_t b) const
|
||||
{
|
||||
if (((to & 0x10) && (a < b)) ||
|
||||
((to & 0x08) && (a > b)) ||
|
||||
((to & 0x04) && (a == b)) ||
|
||||
((to & 0x02) && ((uint64_t)a < (uint64_t)b)) ||
|
||||
((to & 0x01) && ((uint64_t)a > (uint64_t)b))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
suffix() const
|
||||
{
|
||||
std::string str;
|
||||
|
||||
switch (to) {
|
||||
case 1: str = "lgt"; break;
|
||||
case 2: str = "llt"; break;
|
||||
case 4: str = "eq"; break;
|
||||
case 5: str = "lge"; break;
|
||||
case 6: str = "lle"; break;
|
||||
case 8: str = "gt"; break;
|
||||
case 12: str = "ge"; break;
|
||||
case 16: str = "lt"; break;
|
||||
case 20: str = "le"; break;
|
||||
case 24: str = "ne"; break;
|
||||
case 31: str = "u"; break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for integer immediate trap operations.
|
||||
*/
|
||||
class IntImmTrapOp : public IntTrapOp
|
||||
{
|
||||
protected:
|
||||
int32_t si;
|
||||
|
||||
/// Constructor
|
||||
IntImmTrapOp(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: IntTrapOp(mnem, _machInst, __opClass),
|
||||
si(sext<16>(machInst.si))
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
} // namespace PowerISA
|
||||
|
||||
#endif //__ARCH_POWER_INSTS_INTEGER_HH__
|
||||
|
||||
@@ -36,6 +36,11 @@
|
||||
//
|
||||
decode PO default Unknown::unknown() {
|
||||
|
||||
format IntImmTrapOp {
|
||||
2: tdi({{ Ra }});
|
||||
3: twi({{ Ra_sw }});
|
||||
}
|
||||
|
||||
4: decode VA_XO {
|
||||
|
||||
// Arithmetic instructions that use source registers Ra, Rb and Rc,
|
||||
@@ -325,6 +330,8 @@ decode PO default Unknown::unknown() {
|
||||
cr = makeCRFieldSigned((int32_t)Ra, (int32_t)Rb, xer.so);
|
||||
}});
|
||||
|
||||
4: IntTrapOp::tw({{ Ra_sw }}, {{ Rb_sw }});
|
||||
|
||||
format LoadIndexOp {
|
||||
20: lwarx({{
|
||||
Rt = Mem_uw;
|
||||
@@ -379,6 +386,8 @@ decode PO default Unknown::unknown() {
|
||||
60: andc({{ Ra = Rs & ~Rb; }}, true);
|
||||
}
|
||||
|
||||
68: IntTrapOp::td({{ Ra }}, {{ Rb }});
|
||||
|
||||
format LoadIndexOp {
|
||||
84: ldarx({{
|
||||
Rt = Mem_ud;
|
||||
|
||||
@@ -545,3 +545,34 @@ def format IntConcatRotateOp(code, inst_flags = []) {{
|
||||
decoder_output += decoder_output_rc1
|
||||
exec_output += exec_output_rc1
|
||||
}};
|
||||
|
||||
|
||||
def format IntTrapOp(src1, src2, inst_flags = []) {{
|
||||
|
||||
# Add code to set up variables and check for a trap
|
||||
code = 'int64_t src1 = ' + src1 + ';\n'
|
||||
code += 'int64_t src2 = ' + src2 + ';\n'
|
||||
code += 'if (checkTrap(src1, src2)) {\n'
|
||||
code += ' panic("trap generated at %#x", xc->pcState().pc());\n'
|
||||
code += ' return std::make_shared<TrapFault>();\n'
|
||||
code += '}\n'
|
||||
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
GenAluOp(name, Name, 'IntTrapOp', code, inst_flags, BasicDecode,
|
||||
BasicConstructor)
|
||||
}};
|
||||
|
||||
|
||||
def format IntImmTrapOp(src, inst_flags = []) {{
|
||||
|
||||
# Add code to set up variables and check for a trap
|
||||
code = 'int64_t src = ' + src + ';\n'
|
||||
code += 'if (checkTrap(src, si)) {\n'
|
||||
code += ' panic("trap generated at %#x", xc->pcState().pc());\n'
|
||||
code += ' return std::make_shared<TrapFault>();\n'
|
||||
code += '}\n'
|
||||
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
GenAluOp(name, Name, 'IntImmTrapOp', code, inst_flags, BasicDecode,
|
||||
BasicConstructor)
|
||||
}};
|
||||
|
||||
@@ -88,6 +88,9 @@ BitUnion32(ExtMachInst)
|
||||
Bitfield<20, 16> ba;
|
||||
Bitfield<15, 11> bb;
|
||||
|
||||
// Trap instruction fields
|
||||
Bitfield<25, 21> to;
|
||||
|
||||
// FXM field for mtcrf instruction
|
||||
Bitfield<19, 12> fxm;
|
||||
EndBitUnion(ExtMachInst)
|
||||
|
||||
Reference in New Issue
Block a user