From: Sandipan Das Date: Thu, 7 Jun 2018 08:53:20 +0000 (+0530) Subject: arch-power: Fix fixed-point compare instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b1a5a51a81d13850631a83f08ff9cc90c681f80f;p=gem5.git 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 --- diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index a1bf84249..8f7956277 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -48,7 +48,7 @@ IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 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; @@ -277,6 +277,183 @@ IntDispArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const } +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 { diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 44a7678db..d035f512e 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -416,6 +416,71 @@ class IntDispArithOp : public IntArithOp }; +/** + * 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. */ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 43c62afce..73b68bfd8 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -252,19 +252,26 @@ decode PO default Unknown::unknown() { } } - 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 @@ decode PO default Unknown::unknown() { }}); } - 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 54c35ebca..e5e6d2db0 100644 --- a/src/arch/power/isa/formats/integer.isa +++ b/src/arch/power/isa/formats/integer.isa @@ -223,6 +223,57 @@ def format IntDispArithOp(code, inst_flags = []) {{ }}; +// 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 8f499bbf1..b0edce81c 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -53,12 +53,16 @@ BitUnion32(ExtMachInst) // 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;