diff --git a/src/arch/power/faults.hh b/src/arch/power/faults.hh index e20ef8eb53..806f95810f 100644 --- a/src/arch/power/faults.hh +++ b/src/arch/power/faults.hh @@ -82,6 +82,16 @@ class AlignmentFault : public PowerFault } }; + +class TrapFault : public PowerFault +{ + public: + TrapFault() + : PowerFault("Trap") + { + } +}; + } // namespace PowerISA #endif // __ARCH_POWER_FAULTS_HH__ diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index 320350777f..7795b50ef6 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -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(); +} diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 69bc633a5d..600fdf4318 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -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__ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 2742065bf3..6c73b2808c 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -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; diff --git a/src/arch/power/isa/formats/integer.isa b/src/arch/power/isa/formats/integer.isa index 98759eeff5..5f195d7271 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -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();\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();\n' + code += '}\n' + + (header_output, decoder_output, decode_block, exec_output) = \ + GenAluOp(name, Name, 'IntImmTrapOp', code, inst_flags, BasicDecode, + BasicConstructor) +}}; diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index b0d943b1fd..c7ff900532 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -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)