if (!myMnemonic.compare("or") && _srcRegIdx[0] == _srcRegIdx[1]) {
myMnemonic = "mr";
printSecondSrc = false;
- } else if (!myMnemonic.compare("mtlr") || !myMnemonic.compare("cmpi")) {
+ } else if (!myMnemonic.compare("mtlr")) {
printDest = false;
} else if (!myMnemonic.compare("mflr")) {
printSrcs = false;
}
+string
+IntCompOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+ stringstream ss;
+ bool printFieldPrefix = false;
+ bool printLength = true;
+
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("cmp")) {
+ if (length) {
+ myMnemonic = "cmpd";
+ } else {
+ myMnemonic = "cmpw";
+ }
+ printFieldPrefix = true;
+ printLength = false;
+ } else if (!myMnemonic.compare("cmpl")) {
+ if (length) {
+ myMnemonic = "cmpld";
+ } else {
+ myMnemonic = "cmplw";
+ }
+ printFieldPrefix = true;
+ printLength = false;
+ }
+
+ ccprintf(ss, "%-10s ", myMnemonic);
+
+ // Print the first destination only
+ if (printFieldPrefix) {
+ if (field > 0) {
+ ss << "cr" << field;
+ }
+ } else {
+ ss << field;
+ }
+
+ // Print the length
+ if (printLength) {
+ if (!printFieldPrefix || field > 0) {
+ ss << ", ";
+ }
+ ss << length;
+ }
+
+ // Print the first source register
+ if (_numSrcRegs > 0) {
+ if (!printFieldPrefix || field > 0 || printLength) {
+ ss << ", ";
+ }
+ printReg(ss, _srcRegIdx[0]);
+
+ // Print the second source register
+ if (_numSrcRegs > 1) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[1]);
+ }
+ }
+
+ return ss.str();
+}
+
+
+string
+IntImmCompOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+{
+ stringstream ss;
+ bool printFieldPrefix = false;
+ bool printLength = true;
+
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("cmpi")) {
+ if (length) {
+ myMnemonic = "cmpdi";
+ } else {
+ myMnemonic = "cmpwi";
+ }
+ printFieldPrefix = true;
+ printLength = false;
+ }
+
+ ccprintf(ss, "%-10s ", myMnemonic);
+
+ // Print the first destination only
+ if (printFieldPrefix) {
+ if (field > 0) {
+ ss << "cr" << field;
+ }
+ } else {
+ ss << field;
+ }
+
+ // Print the length
+ if (printLength) {
+ if (!printFieldPrefix || field > 0) {
+ ss << ", ";
+ }
+ ss << length;
+ }
+
+ // Print the first source register
+ if (_numSrcRegs > 0) {
+ if (!printFieldPrefix || field > 0 || printLength) {
+ ss << ", ";
+ }
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ // Print the immediate value
+ ss << ", " << simm;
+
+ return ss.str();
+}
+
+
+string
+IntImmCompLogicOp::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+{
+ stringstream ss;
+ bool printFieldPrefix = false;
+ bool printLength = true;
+
+ // Generate the correct mnemonic
+ string myMnemonic(mnemonic);
+
+ // Special cases
+ if (!myMnemonic.compare("cmpli")) {
+ if (length) {
+ myMnemonic = "cmpldi";
+ } else {
+ myMnemonic = "cmplwi";
+ }
+ printFieldPrefix = true;
+ printLength = false;
+ }
+
+ ccprintf(ss, "%-10s ", myMnemonic);
+
+ // Print the first destination only
+ if (printFieldPrefix) {
+ if (field > 0) {
+ ss << "cr" << field;
+ }
+ } else {
+ ss << field;
+ }
+
+ // Print the mode
+ if (printLength) {
+ if (!printFieldPrefix || field > 0) {
+ ss << ", ";
+ }
+ ss << length;
+ }
+
+ // Print the first source register
+ if (_numSrcRegs > 0) {
+ if (!printFieldPrefix || field > 0 || printLength) {
+ ss << ", ";
+ }
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ // Print the immediate value
+ ss << ", " << uimm;
+
+ return ss.str();
+}
+
+
string
IntShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
};
+/**
+ * Class for integer compare operations.
+ */
+class IntCompOp : public IntOp
+{
+ protected:
+
+ uint32_t length;
+ uint32_t field;
+
+ /// Constructor
+ IntCompOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : IntOp(mnem, _machInst, __opClass),
+ length(machInst.l),
+ field(machInst.bf)
+ {
+ }
+
+ std::string generateDisassembly(
+ Addr pc, const SymbolTable *symtab) const override;
+};
+
+
+/**
+ * Class for integer immediate compare operations.
+ */
+class IntImmCompOp : public IntCompOp
+{
+ protected:
+
+ int32_t simm;
+
+ /// Constructor
+ IntImmCompOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : IntCompOp(mnem, _machInst, __opClass),
+ simm((int16_t)machInst.si)
+ {
+ }
+
+ std::string generateDisassembly(
+ Addr pc, const SymbolTable *symtab) const override;
+};
+
+
+/**
+ * Class for integer immediate compare logical operations.
+ */
+class IntImmCompLogicOp : public IntCompOp
+{
+ protected:
+
+ uint32_t uimm;
+
+ /// Constructor
+ IntImmCompLogicOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : IntCompOp(mnem, _machInst, __opClass),
+ uimm(machInst.ui)
+ {
+ }
+
+ std::string generateDisassembly(
+ Addr pc, const SymbolTable *symtab) const override;
+};
+
+
/**
* Class for integer operations with a shift.
*/
}
}
- format IntImmOp {
- 10: cmpli({{
- Xer xer = XER;
- uint32_t cr = makeCRField(Ra, (uint32_t)uimm, xer.so);
- CR = insertCRField(CR, BF, cr);
- }});
+ format IntImmCompOp {
11: cmpi({{
- Xer xer = XER;
- uint32_t cr = makeCRField(Ra_sw, (int32_t)imm, xer.so);
- CR = insertCRField(CR, BF, cr);
- }});
+ if (length) {
+ cr = makeCRField(Ra_sd, simm, xer.so);
+ } else {
+ cr = makeCRField((int32_t)Ra_sd, simm, xer.so);
+ }
+ }});
}
+ format IntImmCompLogicOp {
+ 10: cmpli({{
+ if (length) {
+ cr = makeCRField(Ra, uimm, xer.so);
+ } else {
+ cr = makeCRField((uint32_t)Ra, uimm, xer.so);
+ }
+ }});
+ }
+
format IntImmLogicOp {
24: ori({{ Ra = Rs | uimm; }});
25: oris({{ Ra = Rs | (uimm << 16); }});
}});
}
- format IntOp {
+ format IntCompOp {
0: cmp({{
- Xer xer = XER;
- uint32_t cr = makeCRField(Ra_sw, Rb_sw, xer.so);
- CR = insertCRField(CR, BF, cr);
+ if (length) {
+ cr = makeCRField(Ra_sd, Rb_sd, xer.so);
+ } else {
+ cr = makeCRField((int32_t)Ra_sd, (int32_t)Rb_sd, xer.so);
+ }
}});
32: cmpl({{
- Xer xer = XER;
- uint32_t cr = makeCRField(Ra, Rb, xer.so);
- CR = insertCRField(CR, BF, cr);
+ if (length) {
+ cr = makeCRField(Ra, Rb, xer.so);
+ } else {
+ cr = makeCRField((uint32_t)Ra, (uint32_t)Rb, xer.so);
+ }
}});
}
}};
+// Integer compare instructions.
+def format IntCompOp(code, inst_flags = []) {{
+
+ # Add code to setup variables
+ code = 'uint32_t cr M5_VAR_USED = 0;\n' + code
+ code += 'CR = insertCRField(CR, field, cr);\n'
+
+ # Add code to access XER
+ code = readXERCode + code
+
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntCompOp', code, inst_flags, BasicDecode,
+ BasicConstructor)
+}};
+
+
+// Integer immediate compare instructions.
+def format IntImmCompOp(code, inst_flags = []) {{
+
+ # Add code to setup variables
+ code = 'uint32_t cr M5_VAR_USED = 0;\n' + code
+ code += 'CR = insertCRField(CR, field, cr);\n'
+
+ # Add code to access XER
+ code = readXERCode + code
+
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntImmCompOp', code, inst_flags, BasicDecode,
+ BasicConstructor)
+}};
+
+
+// Integer immediate compare logical instructions.
+def format IntImmCompLogicOp(code, inst_flags = []) {{
+
+ # Add code to setup variables
+ code = 'uint32_t cr M5_VAR_USED = 0;\n' + code
+ code += 'CR = insertCRField(CR, field, cr);\n'
+
+ # Add code to access XER
+ code = readXERCode + code
+
+ # Generate the class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntImmCompLogicOp', code, inst_flags,
+ BasicDecode, BasicConstructor)
+}};
+
+
// Integer instructions that perform logic operations. The result is
// always written into Ra. All instructions have 2 versions depending on
// whether the Rc bit is set to compute the CR0 code. This is determined
// Immediate fields
Bitfield<15, 0> si;
+ Bitfield<15, 0> ui;
Bitfield<15, 0> d;
Bitfield<15, 2> ds;
Bitfield<15, 6> d0;
Bitfield<20, 16> d1;
Bitfield< 1, 0> d2;
+ // Compare fields
+ Bitfield<21> l;
+
// Special purpose register identifier
Bitfield<20, 11> spr;
Bitfield<25, 2> li;