Sandipan Das has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/16625
Change subject: arch-power: Fix fixed-point compare instructions
......................................................................
arch-power: Fix fixed-point compare instructions
This fixes the following compare instructions:
* Compare (cmp)
* Compare Logical (cmpl)
* Compare Immediate (cmpi)
* Compare Logical Immediate (cmpli)
Instead of always doing a 32-bit comparison, these instructions
now use the length field to determine the type of comparison to
be done. The comparison can either be based on the lower order
32 bits or on all 64 bits of the values.
This also fixes disassembly generation for all of the above.
Change-Id: I6a9f783efa9ef2f2ef3c16eada61074d6f798a20
Signed-off-by: Sandipan Das <[email protected]>
---
M src/arch/power/insts/integer.cc
M src/arch/power/insts/integer.hh
M src/arch/power/isa/decoder.isa
M src/arch/power/isa/formats/integer.isa
M src/arch/power/types.hh
5 files changed, 326 insertions(+), 18 deletions(-)
diff --git a/src/arch/power/insts/integer.cc
b/src/arch/power/insts/integer.cc
index a1bf842..8f79562 100644
--- a/src/arch/power/insts/integer.cc
+++ b/src/arch/power/insts/integer.cc
@@ -48,7 +48,7 @@
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;
@@ -278,6 +278,183 @@
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
{
stringstream ss;
diff --git a/src/arch/power/insts/integer.hh
b/src/arch/power/insts/integer.hh
index 4ee258c..5c4321b 100644
--- a/src/arch/power/insts/integer.hh
+++ b/src/arch/power/insts/integer.hh
@@ -429,6 +429,71 @@
/**
+ * 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.
*/
class IntShiftOp : public IntOp
diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa
index e9c1fce..1838637 100644
--- a/src/arch/power/isa/decoder.isa
+++ b/src/arch/power/isa/decoder.isa
@@ -252,19 +252,26 @@
}
}
- 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); }});
@@ -453,17 +460,21 @@
}});
}
- 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);
+ }
}});
}
diff --git a/src/arch/power/isa/formats/integer.isa
b/src/arch/power/isa/formats/integer.isa
index 54c35eb..e5e6d2d 100644
--- a/src/arch/power/isa/formats/integer.isa
+++ b/src/arch/power/isa/formats/integer.isa
@@ -223,6 +223,57 @@
}};
+// 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
diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh
index 8f499bb..b0edce8 100644
--- a/src/arch/power/types.hh
+++ b/src/arch/power/types.hh
@@ -53,12 +53,16 @@
// 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;
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16625
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I6a9f783efa9ef2f2ef3c16eada61074d6f798a20
Gerrit-Change-Number: 16625
Gerrit-PatchSet: 1
Gerrit-Owner: Sandipan Das <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev